1/* 2 * ---------------------------------------------------------------------------- 3 * "THE BEER-WARE LICENSE" (Revision 42): 4 * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you 5 * can do whatever you want with this stuff. If we meet some day, and you think 6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 7 * ---------------------------------------------------------------------------- |
8 */ 9 |
10/* 11 * It has since been changed by Brandon Gillespie, the end result is not 12 * too clean, but it is clear and modular; there is no need for crypt() 13 * to be optimized (and actually a desire for the opposite) so I am not 14 * overly concerned. 15 */ |
16 |
17/* 18 * Assumptions made with the format of passwords: 19 * 20 * + Any password beginning with a dollar-sign is assumed to be in 21 * the Modular Crypt Format (MCF), namely: $tag$salt$hash. Any 22 * algorithms added will also use this format. Other MCF assumptions: 23 * + The algorithm tag (field 1) will be less than five characters 24 * long (yay, arbitrary limits). Anything longer is ignored. 25 * New algorithm names are not allowed to be fully numeric as 26 * anything fully numeric is mapped from other OS's not following 27 * our standard, and from older versions of this standard (such as 28 * $1$ for MD5 passwords, rather than $MD5$). 29 * + The salt can be up to 16 characters in length (more arbitrary 30 * limits). 31 * + An invalid or unrecognized algorithm tag will default to use the 32 * 'best' encryption method--whatever that may be at the time. 33 * + If the MCF is not specified, use the 'best' method, unless DES 34 * is installed--then use DES. 35 * + Any password beginning with an underscore '_' is assumed to be 36 * the Extended DES Format, which has its own salt requirements, 37 * and is not the same as the MCF. 38 * + Salt must be limited to the same ascii64 character set the hash 39 * is encoded in (namely "./0-9A-Za-z"). 40 */ 41 |
42#include <unistd.h> 43#include <stdio.h> |
44#include <stdlib.h> |
45#include <string.h> |
46#include <ctype.h> |
47 |
48#define _CRYPT_C_ |
49 |
50#include "crypt.h" |
51 |
52#ifndef TRUE 53#define TRUE 1 54#endif 55 56#ifndef FALSE 57#define FALSE 0 58#endif 59 60/* 61 * commonly used througout all algorithms 62 */ 63 64static unsigned char ascii64[] = /* 0 ... 63 => ascii - 64 */ 65 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 66 67void |
68to64(s, v, n) 69 char *s; 70 unsigned long v; 71 int n; 72{ |
73 while (--n >= 0) { |
74 *s++ = ascii64[v&0x3f]; |
75 v >>= 6; 76 } 77} 78 |
79static char * hash_word(password, salt, output) 80 const char *password; 81 const char *salt; 82 char *output; |
83{ |
84 unsigned char spbuf[_CRYPT_MAX_SALT_LEN+1], 85 pwbuf[_CRYPT_OUTPUT_SIZE+1], 86 * ep, * sp, * pw; 87 unsigned int sl, pl, 88 tag = _CRYPT_DEFAULT_VERSION, 89 mcf = FALSE; |
90 |
91 memset(spbuf, 0, _CRYPT_MAX_SALT_LEN+1); 92 memset(pwbuf, 0, _CRYPT_MAX_SALT_LEN+1); 93 strncpy((char *) spbuf, (unsigned char *) salt, _CRYPT_MAX_SALT_LEN); 94 strncpy((char *) pwbuf, (unsigned char *) password, _CRYPT_OUTPUT_SIZE); 95 sp = &spbuf[0]; 96 pw = &pwbuf[0]; 97 pl = strlen((char *) pw); |
98 |
99 /* figure out what type of crypt is wanted */ 100 if (sp && sp[0] == '$') { 101 mcf = TRUE; 102 sp++; 103 if (strncasecmp((char *) sp, "MD5$", 4)==0) { 104 tag = _MD5_CRYPT; 105 sp += 4; 106 } else if (strncasecmp((char *) sp, "1$", 2)==0) { 107 tag = _MD5_CRYPT_OLD; 108 sp += 2; 109 } else if (strncasecmp((char *) sp, "SHA1$", 5)==0) { 110 tag = _SHS_CRYPT; 111 sp += 5; 112 } else { 113 tag = _CRYPT_DEFAULT_VERSION; 114 while (*sp && *sp != '$') 115 sp++; 116 if (*sp == '$') 117 sp++; 118 } 119 } |
120 |
121 /* Refine the salt. Go to the end, it stops at the first '$' or NULL */ 122 for (ep=sp; *ep && *ep != '$'; ep++) 123 continue; |
124 |
125 /* we have to do this so we dont overflow _PASSWORD_LEN */ 126 if ((ep - sp) > 16) { 127 sl = 16; 128 sp[16] = (char) NULL; 129 } else { 130 sl = ep - sp; 131 } |
132 |
133 switch (tag) { 134 case _MD5_CRYPT_OLD: 135 return crypt_md5(pw, pl, sp, sl, output, "$1$"); 136 case _MD5_CRYPT: 137 return crypt_md5(pw, pl, sp, sl, output, "$MD5$"); 138#ifdef DES_CRYPT 139 case _DES_CRYPT: 140 return crypt_des(pw, pl, sp, sl, output, ""); 141#endif 142 /* dropping a DES password through will likely cause problems, 143 but at least crypt() will return as it says it will (we cannot 144 return an error condition) */ 145 case _SHS_CRYPT: 146 default: 147 return crypt_shs(pw, pl, sp, sl, output, "$SHA1$"); 148 } 149} |
150 |
151char * 152crypt(password, salt) 153 const char *password; 154 const char *salt; 155{ 156 static char output[_CRYPT_OUTPUT_SIZE]; |
157 |
158 return hash_word(password, salt, output); 159} |
160 |
161char * 162malloc_crypt(password, salt) 163 const char *password; 164 const char *salt; 165{ 166 char * output; |
167 |
168 output = (char *) malloc(sizeof(char) * _CRYPT_OUTPUT_SIZE); 169 return hash_word(password, salt, output); 170} |
171 |
172int 173match_crypted(possible, crypted) 174 const char * possible, 175 * crypted; 176{ 177 char * pc; 178 int match; |
179 |
180 pc = malloc_crypt(possible, crypted); |
181 |
182 match = !strcmp(pc, crypted); |
183 |
184 free(pc); |
185 |
186 return match; |
187} 188 |
189#undef _CRYPT_C_ |