]>
Commit | Line | Data |
---|---|---|
6e6374cb | 1 | /* |
2 | * $Source$ | |
3 | * $Author$ | |
4 | * $Header$ | |
5 | * | |
7189310c | 6 | * (c) Copyright 1988 by the Massachusetts Institute of Technology. |
7 | * For copying and distribution information, please see the file | |
8 | * <mit-copyright.h>. | |
6e6374cb | 9 | */ |
10 | ||
11 | #ifndef lint | |
12 | static char *rcsid_reg_stubs_c = "$Header$"; | |
7ff930df | 13 | #endif |
7189310c | 14 | |
15 | #include <mit-copyright.h> | |
6e6374cb | 16 | #include <stdio.h> |
7ff930df | 17 | #include <stdlib.h> |
6e6374cb | 18 | #include <sys/types.h> |
19 | #include <sys/time.h> | |
20 | #include <sys/socket.h> | |
8de2273d | 21 | #ifdef _AIX_SOURCE |
22 | #include <sys/select.h> | |
23 | #endif | |
6e6374cb | 24 | #include <netinet/in.h> |
25 | #include <netdb.h> | |
26 | #include <des.h> | |
b7ed754f | 27 | #include <krb.h> |
28 | #include <krb_err.h> | |
6e6374cb | 29 | #include <errno.h> |
8defc06b | 30 | #include <moira.h> |
31 | #include <moira_site.h> | |
7ff930df | 32 | #include <hesiod.h> |
6e6374cb | 33 | #include "ureg_err.h" |
34 | #include "ureg_proto.h" | |
f071d8a7 | 35 | #include <string.h> |
b7ed754f | 36 | #include <ctype.h> |
6e6374cb | 37 | |
38 | static int reg_sock = -1; | |
8edc0757 | 39 | static int seq_no = 0; |
b7ed754f | 40 | static char *host; |
6e6374cb | 41 | extern errno; |
42 | #define UNKNOWN_HOST -1 | |
43 | #define UNKNOWN_SERVICE -2 | |
44 | ||
8b7874ce | 45 | #ifndef FD_SET |
46 | #define FD_ZERO(p) ((p)->fds_bits[0] = 0) | |
47 | #define FD_SET(n, p) ((p)->fds_bits[0] |= (1 << (n))) | |
48 | #define FD_ISSET(n, p) ((p)->fds_bits[0] & (1 << (n))) | |
49 | #endif /* FD_SET */ | |
50 | ||
6e6374cb | 51 | ureg_init() |
52 | { | |
53 | struct servent *sp; | |
b7ed754f | 54 | char **p, *s; |
6e6374cb | 55 | struct hostent *hp; |
f071d8a7 | 56 | struct sockaddr_in s_in; |
6e6374cb | 57 | |
e0cddd92 | 58 | initialize_ureg_error_table(); |
a85aba2f | 59 | initialize_krb_error_table(); |
60 | initialize_sms_error_table(); | |
7f0e4572 | 61 | initialize_kadm_error_table(); |
a85aba2f | 62 | |
8edc0757 | 63 | seq_no = getpid(); |
64 | ||
028ff1c1 | 65 | host = NULL; |
66 | host = getenv("REGSERVER"); | |
67 | #ifdef HESIOD | |
68 | if (!host || (strlen(host) == 0)) { | |
69 | p = hes_resolve("registration", "sloc"); | |
70 | if (p) host = *p; | |
71 | } | |
7ff930df | 72 | #endif |
028ff1c1 | 73 | if (!host || (strlen(host) == 0)) { |
8defc06b | 74 | host = strsave(MOIRA_SERVER); |
f071d8a7 | 75 | s = strchr(host, ':'); |
14ef68d0 | 76 | if (s) *s = 0; |
028ff1c1 | 77 | } |
78 | hp = gethostbyname(host); | |
8de2273d | 79 | host = strsave(hp->h_name); |
6e6374cb | 80 | if (hp == NULL) return UNKNOWN_HOST; |
81 | ||
82 | sp = getservbyname("sms_ureg", "udp"); | |
83 | ||
84 | if (sp == NULL) return UNKNOWN_SERVICE; | |
85 | ||
86 | (void) close(reg_sock); | |
87 | reg_sock = socket(AF_INET, SOCK_DGRAM, 0); | |
88 | if (reg_sock < 0) return errno; | |
89 | ||
559fc722 | 90 | memset((char *)&s_in, 0, sizeof(s_in)); |
f071d8a7 | 91 | s_in.sin_port = sp->s_port; |
92 | memcpy((char *)&s_in.sin_addr, hp->h_addr, sizeof(struct in_addr)); | |
93 | s_in.sin_family = AF_INET; | |
6e6374cb | 94 | |
7ff930df | 95 | if (connect(reg_sock, (struct sockaddr *)&s_in, sizeof(s_in)) < 0) |
6e6374cb | 96 | return errno; |
97 | return 0; | |
98 | } | |
99 | ||
6e6374cb | 100 | int |
101 | verify_user(first, last, idnumber, hashidnumber, login) | |
102 | char *first, *last, *idnumber, *hashidnumber, *login; | |
103 | { | |
104 | char buf[1024]; | |
105 | int version = ntohl((u_long)1); | |
106 | int call = ntohl((u_long)UREG_VERIFY_USER); | |
c1b9c340 | 107 | des_cblock key; |
108 | des_key_schedule ks; | |
6e6374cb | 109 | register char *bp = buf; |
110 | register int len; | |
111 | char crypt_src[1024]; | |
112 | ||
f071d8a7 | 113 | memcpy(bp, (char *)&version, sizeof(int)); |
6e6374cb | 114 | bp += sizeof(int); |
115 | seq_no++; | |
f071d8a7 | 116 | memcpy(bp, (char *)&seq_no, sizeof(int)); |
6e6374cb | 117 | |
118 | bp += sizeof(int); | |
119 | ||
f071d8a7 | 120 | memcpy(bp, (char *)&call, sizeof(int)); |
6e6374cb | 121 | |
122 | bp += sizeof(int); | |
123 | ||
124 | (void) strcpy(bp, first); | |
125 | bp += strlen(bp)+1; | |
126 | ||
127 | (void) strcpy(bp, last); | |
128 | bp += strlen(bp)+1; | |
129 | ||
130 | len = strlen(idnumber) + 1; | |
f071d8a7 | 131 | memcpy(crypt_src, idnumber, len); |
6e6374cb | 132 | |
f071d8a7 | 133 | memcpy(crypt_src+len, hashidnumber, 13); |
6e6374cb | 134 | |
c1b9c340 | 135 | des_string_to_key(hashidnumber, key); |
136 | des_key_sched(key, ks); | |
e4b6711e | 137 | des_pcbc_encrypt(crypt_src, bp, len+13, ks, key, DES_ENCRYPT); |
6e6374cb | 138 | bp += len+14+8; |
139 | len = bp - buf; | |
140 | return do_call(buf, len, seq_no, login); | |
141 | } | |
142 | ||
5dee7862 | 143 | do_operation(first, last, idnumber, hashidnumber, data, opcode) |
144 | char *first, *last, *idnumber, *hashidnumber, *data; | |
145 | u_long opcode; | |
6e6374cb | 146 | { |
147 | char buf[1024]; | |
148 | int version = ntohl((u_long)1); | |
5dee7862 | 149 | int call = ntohl(opcode); |
c1b9c340 | 150 | des_cblock key; |
151 | des_key_schedule ks; | |
6e6374cb | 152 | register char *bp = buf; |
153 | register int len; | |
6e6374cb | 154 | |
155 | char crypt_src[1024]; | |
156 | char *cbp; | |
157 | ||
f071d8a7 | 158 | memcpy(bp, (char *)&version, sizeof(int)); |
6e6374cb | 159 | bp += sizeof(int); |
160 | seq_no++; | |
f071d8a7 | 161 | memcpy(bp, (char *)&seq_no, sizeof(int)); |
6e6374cb | 162 | |
163 | bp += sizeof(int); | |
164 | ||
f071d8a7 | 165 | memcpy(bp, (char *)&call, sizeof(int)); |
6e6374cb | 166 | |
167 | bp += sizeof(int); | |
168 | ||
169 | (void) strcpy(bp, first); | |
170 | bp += strlen(bp)+1; | |
171 | ||
172 | (void) strcpy(bp, last); | |
173 | bp += strlen(bp)+1; | |
174 | ||
175 | len = strlen(idnumber) + 1; | |
176 | cbp = crypt_src; | |
177 | ||
f071d8a7 | 178 | memcpy(crypt_src, idnumber, len); |
6e6374cb | 179 | cbp += len; |
180 | ||
f071d8a7 | 181 | memcpy(cbp, hashidnumber, 14); |
6e6374cb | 182 | cbp += 14; |
183 | ||
5dee7862 | 184 | len = strlen(data) + 1; |
f071d8a7 | 185 | memcpy(cbp, data, len); |
6e6374cb | 186 | cbp += len; |
187 | ||
188 | len = cbp - crypt_src; | |
c1b9c340 | 189 | des_string_to_key(hashidnumber, key); |
190 | des_key_sched(key, ks); | |
191 | des_pcbc_encrypt(crypt_src, bp, len, ks, key, 1); | |
6e6374cb | 192 | len = ((len + 7) >> 3) << 3; |
193 | bp += len; | |
194 | ||
195 | len = bp - buf; | |
196 | return do_call(buf, len, seq_no, 0); | |
197 | ||
198 | } | |
199 | ||
5dee7862 | 200 | grab_login(first, last, idnumber, hashidnumber, login) |
201 | char *first, *last, *idnumber, *hashidnumber, *login; | |
6e6374cb | 202 | { |
5dee7862 | 203 | return(do_operation(first, last, idnumber, hashidnumber, login, |
204 | UREG_RESERVE_LOGIN)); | |
205 | } | |
6e6374cb | 206 | |
5dee7862 | 207 | enroll_login(first, last, idnumber, hashidnumber, login) |
208 | char *first, *last, *idnumber, *hashidnumber, *login; | |
209 | { | |
210 | return(do_operation(first, last, idnumber, hashidnumber, login, | |
211 | UREG_SET_IDENT)); | |
212 | } | |
6e6374cb | 213 | |
5dee7862 | 214 | set_password(first, last, idnumber, hashidnumber, password) |
215 | char *first, *last, *idnumber, *hashidnumber, *password; | |
216 | { | |
217 | return(do_operation(first, last, idnumber, hashidnumber, password, | |
218 | UREG_SET_PASSWORD)); | |
219 | } | |
6e6374cb | 220 | |
5dee7862 | 221 | get_krb(first, last, idnumber, hashidnumber, password) |
222 | char *first, *last, *idnumber, *hashidnumber, *password; | |
223 | { | |
224 | return(do_operation(first, last, idnumber, hashidnumber, password, | |
225 | UREG_GET_KRB)); | |
6e6374cb | 226 | } |
227 | ||
b7ed754f | 228 | |
229 | /* The handles the operations for secure passwords. | |
8de2273d | 230 | * To find out if a user has a secure instance, the newpasswd |
231 | * field is ignored (but must be a valid char *) | |
b7ed754f | 232 | * and the opcode = UREG_GET_SECURE need to be specified (but the |
233 | * other strings must be valid char*'s). This will return | |
234 | * UREG_ALREADY_REGISTERED if it is set, or SUCCESS if not. | |
235 | * To set the password, fill in the rest of the fields, and | |
236 | * use opcode = UREG_SET_SECURE. This returns SUCCESS or any number | |
237 | * of failure codes. | |
238 | */ | |
239 | ||
240 | do_secure_operation(login, idnumber, passwd, newpasswd, opcode) | |
241 | char *login, *idnumber, *passwd, *newpasswd; | |
242 | u_long opcode; | |
243 | { | |
244 | char buf[1500], data[128], tktstring[128]; | |
245 | int version = ntohl((u_long)1); | |
246 | int call = ntohl(opcode); | |
247 | char inst[INST_SZ], hosti[INST_SZ]; | |
248 | char *bp = buf, *src, *dst, *realm; | |
249 | int len, status, i; | |
250 | KTEXT_ST cred; | |
251 | CREDENTIALS creds; | |
252 | Key_schedule keys; | |
253 | char *krb_get_phost(), *krb_realmofhost(); | |
dcaf7263 | 254 | #ifdef POSIX |
255 | memmove(bp, (char *)&version, sizeof(int)); | |
256 | #else | |
b7ed754f | 257 | bcopy((char *)&version, bp, sizeof(int)); |
dcaf7263 | 258 | #endif |
b7ed754f | 259 | bp += sizeof(int); |
260 | seq_no++; | |
dcaf7263 | 261 | #ifdef POSIX |
262 | memmove(bp, (char *)&seq_no, sizeof(int)); | |
263 | #else | |
b7ed754f | 264 | bcopy((char *)&seq_no, bp, sizeof(int)); |
dcaf7263 | 265 | #endif |
b7ed754f | 266 | |
267 | bp += sizeof(int); | |
dcaf7263 | 268 | #ifdef POSIX |
269 | memmove(bp, (char *)&call, sizeof(int)); | |
270 | #else | |
b7ed754f | 271 | bcopy((char *)&call, bp, sizeof(int)); |
dcaf7263 | 272 | #endif |
b7ed754f | 273 | |
274 | bp += sizeof(int); | |
275 | ||
276 | /* put the login name in the firstname field */ | |
277 | (void) strcpy(bp, login); | |
278 | bp += strlen(bp)+1; | |
279 | ||
280 | /* the old lastname field */ | |
281 | (void) strcpy(bp, ""); | |
282 | bp += strlen(bp)+1; | |
283 | ||
284 | /* don't overwrite existing ticket file */ | |
285 | (void) sprintf(tktstring, "/tmp/tkt_cpw_%d",getpid()); | |
286 | krb_set_tkt_string(tktstring); | |
287 | ||
288 | /* get realm and canonizalized hostname of server */ | |
289 | realm = krb_realmofhost(host); | |
290 | for (src = host, dst = hosti; *src && *src != '.'; src++) | |
291 | if (isupper(*src)) | |
292 | *dst++ = tolower(*src); | |
293 | else | |
294 | *dst++ = *src; | |
295 | *dst = 0; | |
296 | inst[0] = 0; | |
297 | inst[0] = 0; | |
298 | ||
299 | /* get changepw tickets. We use this service because it's the | |
300 | * only one that guarantees we used the password rather than a | |
301 | * ticket granting ticket. | |
302 | */ | |
303 | status = krb_get_pw_in_tkt(login, inst, realm, | |
304 | "changepw", hosti, 5, passwd); | |
8de2273d | 305 | if (status) return (status + krb_err_base); |
b7ed754f | 306 | |
307 | status = krb_mk_req(&cred, "changepw", hosti, realm, 0); | |
8de2273d | 308 | if (status) return (status + krb_err_base); |
b7ed754f | 309 | |
310 | /* round up to word boundry */ | |
311 | bp = (char *)((((u_long)bp)+3)&0xfffffffc); | |
312 | ||
313 | /* put the ticket in the packet */ | |
314 | len = cred.length; | |
315 | cred.length = htonl(cred.length); | |
dcaf7263 | 316 | #ifdef POSIX |
317 | memmove(bp, &(cred), sizeof(int)+len); | |
318 | #else | |
b7ed754f | 319 | bcopy(&(cred), bp, sizeof(int)+len); |
dcaf7263 | 320 | #endif |
b7ed754f | 321 | #ifdef DEBUG |
322 | com_err("test", 0, "Cred: length %d", len); | |
323 | for (i = 0; i < len; i += 16) | |
324 | com_err("test", 0, " %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", | |
325 | cred.dat[i+0], cred.dat[i+1], cred.dat[i+2], cred.dat[i+3], | |
326 | cred.dat[i+4], cred.dat[i+5], cred.dat[i+6], cred.dat[i+7], | |
327 | cred.dat[i+8], cred.dat[i+9], cred.dat[i+10], cred.dat[i+11], | |
328 | cred.dat[i+12], cred.dat[i+13], cred.dat[i+14], cred.dat[i+15]); | |
329 | #endif /* DEBUG */ | |
330 | bp += sizeof(int) + len; | |
331 | ||
332 | /* encrypt the data in the session key */ | |
333 | sprintf(data, "%s,%s", idnumber, newpasswd); | |
334 | len = strlen(data); | |
335 | len = ((len + 7) >> 3) << 3; | |
336 | ||
337 | status = krb_get_cred("changepw", hosti, realm, &creds); | |
338 | if (status) { | |
dcaf7263 | 339 | memset(data, 0, strlen(data)); |
b7ed754f | 340 | return (status + krb_err_base); |
341 | } | |
342 | dest_tkt(); | |
343 | ||
344 | des_key_sched(creds.session, keys); | |
345 | des_pcbc_encrypt(data, bp + sizeof(int), len, keys, creds.session, 1); | |
346 | *((int *)bp) = htonl(len); | |
dcaf7263 | 347 | memset(data, 0, strlen(data)); |
b7ed754f | 348 | |
349 | bp += len + sizeof(int); | |
350 | ||
351 | len = bp - buf; | |
352 | return do_call(buf, len, seq_no, 0); | |
353 | ||
354 | } | |
355 | ||
7ff930df | 356 | do_call(buf, len, seq_no, login) |
6e6374cb | 357 | char *buf; |
358 | char *login; | |
359 | int seq_no; | |
360 | int len; | |
361 | { | |
362 | struct timeval timeout; | |
363 | char ibuf[1024]; | |
364 | fd_set set; | |
365 | ||
366 | int retry = 0; | |
367 | ||
368 | do { | |
369 | if (write(reg_sock, buf, len) != len) return errno; | |
370 | ||
371 | FD_ZERO(&set); | |
372 | FD_SET(reg_sock, &set); | |
aea2c8ee | 373 | timeout.tv_sec = 30; |
6e6374cb | 374 | timeout.tv_usec = 0; |
375 | do { | |
376 | int rtn; | |
f071d8a7 | 377 | struct sockaddr_in s_in; |
378 | int addrlen = sizeof(s_in); | |
6e6374cb | 379 | int vno; |
380 | int sno; | |
381 | int stat; | |
382 | ||
383 | rtn = select(reg_sock+1, &set, (fd_set *)0, (fd_set *)0, &timeout); | |
384 | if (rtn == 0) | |
385 | break; | |
386 | else if (rtn < 0) return errno; | |
387 | ||
7ff930df | 388 | len = recvfrom(reg_sock, ibuf, BUFSIZ, 0, |
389 | (struct sockaddr *)&s_in, &addrlen); | |
6e6374cb | 390 | if (len < 0) return errno; |
391 | if (len < 12) return UREG_BROKEN_PACKET; | |
f071d8a7 | 392 | memcpy((char *)&vno, ibuf, sizeof(long)); |
6e6374cb | 393 | vno = ntohl((u_long)vno); |
394 | if (vno != 1) continue; | |
f071d8a7 | 395 | memcpy((char *)&sno, ibuf + 4, sizeof(long)); |
6e6374cb | 396 | |
397 | if (sno != seq_no) continue; | |
398 | ||
f071d8a7 | 399 | memcpy((char *)&stat, ibuf + 8, sizeof(long)); |
6e6374cb | 400 | stat = ntohl((u_long)stat); |
51ccb3ec | 401 | if (login && len > 12) { |
f071d8a7 | 402 | memcpy(login, ibuf+12, len-12); |
6e6374cb | 403 | login[len-12] = '\0'; |
51ccb3ec | 404 | } else if (login) |
405 | *login = '\0'; | |
6e6374cb | 406 | return stat; |
407 | } while (1); | |
0c8192b9 | 408 | } while (++retry < 10); |
6e6374cb | 409 | return ETIMEDOUT; |
410 | } |