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