1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 1999-2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved	*/
29 
30 #include <stdlib.h>
31 #include <string.h>
32 #include <libintl.h>
33 #include <locale.h>
34 #include <errno.h>
35 #include <unistd.h>
36 #include <ctype.h>
37 #include <syslog.h>
38 #include <sys/time.h>
39 #include "ns_sldap.h"
40 #include "ns_internal.h"
41 #include <crypt.h>
42 
43 static	char		t1[ROTORSIZE];
44 static	char		t2[ROTORSIZE];
45 static	char		t3[ROTORSIZE];
46 static	char		hexdig[] = "0123456789abcdef";
47 
48 static mutex_t		ns_crypt_lock = DEFAULTMUTEX;
49 static boolean_t	crypt_inited = B_FALSE;
50 
51 static int
52 is_cleartext(const char *pwd)
53 {
54 	if (0 == strncmp(pwd, CRYPTMARK, strlen(CRYPTMARK)))
55 		return (FALSE);
56 	return (TRUE);
57 }
58 
59 
60 static char *
61 hex2ascii(char *aString, int aLen)
62 {
63 	char *res;
64 	int i = 0;
65 
66 	if ((res = (char *)calloc(aLen*2 + 1, 1)) == NULL) {
67 		return (NULL);
68 	}
69 	for (;;) {
70 		if (aLen < 1)
71 			break;
72 		res[i] = hexdig[(*aString & 0xf0) >> 4];
73 		res[i + 1] = hexdig[*aString & 0x0f];
74 		i += 2;
75 		aLen--;
76 		aString++;
77 	}
78 	return (res);
79 }
80 
81 
82 static int
83 unhex(char c)
84 {
85 	return (c >= '0' && c <= '9' ? c - '0'
86 		: c >= 'A' && c <= 'F' ? c - 'A' + 10
87 		: c - 'a' + 10);
88 }
89 
90 
91 static char *
92 ascii2hex(char *anHexaStr, int *aResLen)
93 {
94 	int theLen = 0;
95 	char *theRes = malloc(strlen(anHexaStr) /2 + 1);
96 
97 	if (theRes == NULL)
98 		return (NULL);
99 	while (isxdigit(*anHexaStr)) {
100 		theRes[theLen] = unhex(*anHexaStr) << 4;
101 		if (++anHexaStr != '\0') {
102 			theRes[theLen] += unhex(*anHexaStr);
103 			anHexaStr++;
104 		}
105 		theLen++;
106 	}
107 	theRes[theLen] = '\0';
108 	*aResLen = theLen;
109 	return (theRes);
110 }
111 
112 
113 static void
114 c_setup()
115 {
116 	int ic, i, k, temp;
117 	unsigned random;
118 	char buf[13];
119 	int seed;
120 
121 	(void) mutex_lock(&ns_crypt_lock);
122 	if (crypt_inited) {
123 		(void) mutex_unlock(&ns_crypt_lock);
124 		return;
125 	}
126 	(void) strcpy(buf, "Homer J");
127 	buf[8] = buf[0];
128 	buf[9] = buf[1];
129 	(void) strncpy(buf, (char *)crypt(buf, &buf[8]), 13);
130 	seed = 123;
131 	for (i = 0; i < 13; i++)
132 		seed = seed*buf[i] + i;
133 	for (i = 0; i < ROTORSIZE; i++) {
134 		t1[i] = i;
135 		t3[i] = 0;
136 	}
137 	for (i = 0; i < ROTORSIZE; i++) {
138 		seed = 5*seed + buf[i%13];
139 		random = seed % 65521;
140 		k = ROTORSIZE-1 - i;
141 		ic = (random&MASK)%(k+1);
142 		random >>= 8;
143 		temp = t1[k];
144 		t1[k] = t1[ic];
145 		t1[ic] = temp;
146 		if (t3[k] != 0) continue;
147 		ic = (random&MASK) % k;
148 		while (t3[ic] != 0) ic = (ic + 1) % k;
149 		t3[k] = ic;
150 		t3[ic] = k;
151 	}
152 	for (i = 0; i < ROTORSIZE; i++)
153 		t2[t1[i]&MASK] = i;
154 	crypt_inited = B_TRUE;
155 	(void) mutex_unlock(&ns_crypt_lock);
156 }
157 
158 
159 static char *
160 modvalue(char *str, int len, int *mod_len)
161 {
162 	int i, n1, n2;
163 	char *s;
164 
165 	if (!crypt_inited)
166 		c_setup();
167 	i = 0;
168 	n1 = 0;
169 	n2 = 0;
170 	if ((s = (char *)malloc(2 * len + 1)) != NULL) {
171 		while (i < len) {
172 		    s[i] = t2[(t3[(t1[(str[i]+n1)&MASK]+n2)&MASK]-n2)&MASK]-n1;
173 		    i++;
174 		    n1++;
175 		    if (n1 == ROTORSIZE) {
176 			n1 = 0;
177 			n2++;
178 			if (n2 == ROTORSIZE) n2 = 0;
179 		    }
180 		}
181 		s[i] = '\0';
182 		if (mod_len != NULL)
183 		    *mod_len = i;
184 	}
185 	return (s);
186 }
187 
188 
189 char *
190 evalue(char *ptr)
191 {
192 	char *modv, *str, *ev;
193 	int modv_len;
194 	size_t len;
195 
196 	/*
197 	 * if not cleartext, return a copy of what ptr
198 	 * points to as that is what evalue does below.
199 	 */
200 	if (FALSE == is_cleartext(ptr)) {
201 		str = strdup(ptr);
202 		return (str);
203 	}
204 
205 	modv = modvalue(ptr, strlen(ptr), &modv_len);
206 	str = hex2ascii(modv, modv_len);
207 	free(modv);
208 	modv = NULL;
209 	len = strlen(str) + strlen(CRYPTMARK) + 1;
210 	ev = malloc(len);
211 	if (ev == NULL) {
212 		free(str);
213 		return (NULL);
214 	}
215 	(void) snprintf(ev, len, CRYPTMARK "%s", str);
216 	free(str);
217 	str = NULL;
218 	return (ev);
219 }
220 
221 
222 char *
223 dvalue(char *ptr)
224 {
225 	char *modv, *str, *sb;
226 	int len;
227 
228 	/* if cleartext return NULL (error!) */
229 	if (TRUE == is_cleartext(ptr))
230 		return (NULL);
231 
232 	sb = strchr(ptr, '}');
233 	sb++;
234 	len = strlen(sb);
235 	str = ascii2hex(sb, &len);
236 	modv = modvalue(str, len, NULL);
237 	free(str);
238 	str = NULL;
239 	return (modv);
240 }
241