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