Annotation of src/lib/libcrypt/pw_gensalt.c, Revision 1.5
1.5 ! christos 1: /* $NetBSD: pw_gensalt.c,v 1.4 2005/01/12 03:32:52 christos Exp $ */
1.1 christos 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
1.5 ! christos 37: __RCSID("$NetBSD: pw_gensalt.c,v 1.4 2005/01/12 03:32:52 christos Exp $");
1.1 christos 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:
1.3 christos 55: #include "crypt.h"
1.1 christos 56:
57:
58: static const struct pw_salt {
59: const char *name;
1.4 christos 60: int (*gensalt)(char *, size_t, const char *);
1.1 christos 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:
1.4 christos 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:
1.5 ! christos 82: rv = strtoul(str, &ep, 0);
1.4 christos 83:
1.5 ! christos 84: if (str == ep || *ep) {
1.4 christos 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:
1.1 christos 95: int
1.3 christos 96: /*ARGSUSED2*/
1.4 christos 97: __gensalt_old(char *salt, size_t saltsiz, const char *option)
1.1 christos 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
1.3 christos 109: /*ARGSUSED2*/
1.4 christos 110: __gensalt_new(char *salt, size_t saltsiz, const char* option)
1.1 christos 111: {
1.4 christos 112: size_t nrounds;
113:
1.1 christos 114: if (saltsiz < 10) {
115: errno = ENOSPC;
116: return -1;
117: }
1.4 christos 118:
119: if (getnum(option, &nrounds) == -1)
120: return -1;
121:
1.1 christos 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
1.3 christos 135: /*ARGSUSED2*/
1.4 christos 136: __gensalt_md5(char *salt, size_t saltsiz, const char *option)
1.1 christos 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
1.4 christos 153: __gensalt_sha1(char *salt, size_t saltsiz, const char *option)
1.1 christos 154: {
155: int n;
1.4 christos 156: size_t nrounds;
1.1 christos 157:
1.4 christos 158: if (getnum(option, &nrounds) == -1)
159: return -1;
1.1 christos 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
1.4 christos 176: pw_gensalt(char *salt, size_t saltlen, const char *type, const char *option)
1.1 christos 177: {
1.5 ! christos 178: const struct pw_salt *sp;
! 179:
1.1 christos 180: for (sp = salts; sp->name; sp++)
1.4 christos 181: if (strcmp(sp->name, type) == 0)
182: return (*sp->gensalt)(salt, saltlen, option);
1.1 christos 183:
184: errno = EINVAL;
185: return -1;
186: }
CVSweb <webmaster@jp.NetBSD.org>