1 /* $NetBSD: pw_gensalt.c,v 1.5 2005/01/12 05:27:48 christos Exp $ */ 2 3 /* 4 * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Niels Provos. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * 32 * from OpenBSD: pwd_gensalt.c,v 1.9 1998/07/05 21:08:32 provos Exp 33 */ 34 35 #include <sys/cdefs.h> 36 #ifndef lint 37 __RCSID("$NetBSD: pw_gensalt.c,v 1.5 2005/01/12 05:27:48 christos Exp $"); 38 #endif /* not lint */ 39 40 #include <sys/syslimits.h> 41 #include <sys/types.h> 42 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <limits.h> 47 #include <err.h> 48 #include <grp.h> 49 #include <pwd.h> 50 #include <util.h> 51 #include <time.h> 52 #include <errno.h> 53 #include <pwd.h> 54 55 #include "crypt.h" 56 57 58 static const struct pw_salt { 59 const char *name; 60 int (*gensalt)(char *, size_t, const char *); 61 } salts[] = { 62 { "old", __gensalt_old }, 63 { "new", __gensalt_new }, 64 { "newsalt", __gensalt_new }, 65 { "md5", __gensalt_md5 }, 66 { "sha1", __gensalt_sha1 }, 67 { "blowfish", __gensalt_blowfish }, 68 { NULL, NULL } 69 }; 70 71 static int 72 getnum(const char *str, size_t *num) 73 { 74 char *ep; 75 unsigned long rv; 76 77 if (str == NULL) { 78 *num = 0; 79 return 0; 80 } 81 82 rv = strtoul(str, &ep, 0); 83 84 if (str == ep || *ep) { 85 errno = EINVAL; 86 return -1; 87 } 88 89 if (errno == ERANGE && rv == ULONG_MAX) 90 return -1; 91 *num = (size_t)rv; 92 return 0; 93 } 94 95 int 96 /*ARGSUSED2*/ 97 __gensalt_old(char *salt, size_t saltsiz, const char *option) 98 { 99 if (saltsiz < 3) { 100 errno = ENOSPC; 101 return -1; 102 } 103 __crypt_to64(&salt[0], arc4random(), 2); 104 salt[2] = '\0'; 105 return 0; 106 } 107 108 int 109 /*ARGSUSED2*/ 110 __gensalt_new(char *salt, size_t saltsiz, const char* option) 111 { 112 size_t nrounds; 113 114 if (saltsiz < 10) { 115 errno = ENOSPC; 116 return -1; 117 } 118 119 if (getnum(option, &nrounds) == -1) 120 return -1; 121 122 /* Check rounds, 24 bit is max */ 123 if (nrounds < 7250) 124 nrounds = 7250; 125 else if (nrounds > 0xffffff) 126 nrounds = 0xffffff; 127 salt[0] = _PASSWORD_EFMT1; 128 __crypt_to64(&salt[1], (uint32_t)nrounds, 4); 129 __crypt_to64(&salt[5], arc4random(), 4); 130 salt[9] = '\0'; 131 return 0; 132 } 133 134 int 135 /*ARGSUSED2*/ 136 __gensalt_md5(char *salt, size_t saltsiz, const char *option) 137 { 138 if (saltsiz < 13) { /* $1$8salt$\0 */ 139 errno = ENOSPC; 140 return -1; 141 } 142 salt[0] = _PASSWORD_NONDES; 143 salt[1] = '1'; 144 salt[2] = '$'; 145 __crypt_to64(&salt[3], arc4random(), 4); 146 __crypt_to64(&salt[7], arc4random(), 4); 147 salt[11] = '$'; 148 salt[12] = '\0'; 149 return 0; 150 } 151 152 int 153 __gensalt_sha1(char *salt, size_t saltsiz, const char *option) 154 { 155 int n; 156 size_t nrounds; 157 158 if (getnum(option, &nrounds) == -1) 159 return -1; 160 n = snprintf(salt, saltsiz, "%s%u$", SHA1_MAGIC, 161 __crypt_sha1_iterations(nrounds)); 162 /* 163 * The salt can be up to 64 bytes, but 8 164 * is considered enough for now. 165 */ 166 if (n + 9 >= saltsiz) 167 return 0; 168 __crypt_to64(&salt[n], arc4random(), 4); 169 __crypt_to64(&salt[n + 4], arc4random(), 4); 170 salt[n + 8] = '$'; 171 salt[n + 9] = '\0'; 172 return 0; 173 } 174 175 int 176 pw_gensalt(char *salt, size_t saltlen, const char *type, const char *option) 177 { 178 const struct pw_salt *sp; 179 180 for (sp = salts; sp->name; sp++) 181 if (strcmp(sp->name, type) == 0) 182 return (*sp->gensalt)(salt, saltlen, option); 183 184 errno = EINVAL; 185 return -1; 186 } 187