crypt.c revision 42981
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_ 190