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