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