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
is_cleartext(const char * pwd)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 *
hex2ascii(char * aString,int aLen)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
unhex(char c)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 *
ascii2hex(char * anHexaStr,int * aResLen)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
c_setup()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 *
modvalue(char * str,int len,int * mod_len)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] =
173 			    t2[(t3[(t1[(str[i]+n1)&MASK]+n2)&MASK]-n2)&MASK]-n1;
174 			i++;
175 			n1++;
176 			if (n1 == ROTORSIZE) {
177 				n1 = 0;
178 				n2++;
179 				if (n2 == ROTORSIZE)
180 					n2 = 0;
181 			}
182 		}
183 		s[i] = '\0';
184 		if (mod_len != NULL)
185 			*mod_len = i;
186 	}
187 	return (s);
188 }
189 
190 
191 char *
evalue(char * ptr)192 evalue(char *ptr)
193 {
194 	char *modv, *str, *ev;
195 	int modv_len;
196 	size_t len;
197 
198 	/*
199 	 * if not cleartext, return a copy of what ptr
200 	 * points to as that is what evalue does below.
201 	 */
202 	if (FALSE == is_cleartext(ptr)) {
203 		str = strdup(ptr);
204 		return (str);
205 	}
206 
207 	modv = modvalue(ptr, strlen(ptr), &modv_len);
208 	str = hex2ascii(modv, modv_len);
209 	free(modv);
210 	modv = NULL;
211 	len = strlen(str) + strlen(CRYPTMARK) + 1;
212 	ev = malloc(len);
213 	if (ev == NULL) {
214 		free(str);
215 		return (NULL);
216 	}
217 	(void) snprintf(ev, len, CRYPTMARK "%s", str);
218 	free(str);
219 	str = NULL;
220 	return (ev);
221 }
222 
223 
224 char *
dvalue(char * ptr)225 dvalue(char *ptr)
226 {
227 	char *modv, *str, *sb;
228 	int len;
229 
230 	/* if cleartext return NULL (error!) */
231 	if (TRUE == is_cleartext(ptr))
232 		return (NULL);
233 
234 	sb = strchr(ptr, '}');
235 	sb++;
236 	len = strlen(sb);
237 	str = ascii2hex(sb, &len);
238 	modv = modvalue(str, len, NULL);
239 	free(str);
240 	str = NULL;
241 	return (modv);
242 }
243