6 * (c) Copyright 1988 by the Massachusetts Institute of Technology.
7 * For copying and distribution information, please see the file
12 static char *rcsid_reg_stubs_c = "$Header$";
15 #include <mit-copyright.h>
17 #include <sys/types.h>
19 #include <sys/socket.h>
21 #include <sys/select.h>
23 #include <netinet/in.h>
30 #include <moira_site.h>
32 #include "ureg_proto.h"
36 static int reg_sock = -1;
37 static int seq_no = 0;
40 #define UNKNOWN_HOST -1
41 #define UNKNOWN_SERVICE -2
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)))
54 struct sockaddr_in sin;
55 extern char *getenv(), **hes_resolve();
57 initialize_ureg_error_table();
58 initialize_krb_error_table();
59 initialize_sms_error_table();
60 initialize_kadm_error_table();
65 host = getenv("REGSERVER");
67 if (!host || (strlen(host) == 0)) {
68 p = hes_resolve("registration", "sloc");
72 if (!host || (strlen(host) == 0)) {
73 host = strsave(MOIRA_SERVER);
77 hp = gethostbyname(host);
78 host = strsave(hp->h_name);
79 if (hp == NULL) return UNKNOWN_HOST;
81 sp = getservbyname("sms_ureg", "udp");
83 if (sp == NULL) return UNKNOWN_SERVICE;
85 (void) close(reg_sock);
86 reg_sock = socket(AF_INET, SOCK_DGRAM, 0);
87 if (reg_sock < 0) return errno;
89 bzero((char *)&sin, sizeof(sin));
90 sin.sin_port = sp->s_port;
91 bcopy(hp->h_addr, (char *)&sin.sin_addr, sizeof(struct in_addr));
92 sin.sin_family = AF_INET;
94 if (connect(reg_sock, &sin, sizeof(sin)) < 0)
100 verify_user(first, last, idnumber, hashidnumber, login)
101 char *first, *last, *idnumber, *hashidnumber, *login;
104 int version = ntohl((u_long)1);
105 int call = ntohl((u_long)UREG_VERIFY_USER);
108 register char *bp = buf;
110 char crypt_src[1024];
112 bcopy((char *)&version, bp, sizeof(int));
115 bcopy((char *)&seq_no, bp, sizeof(int));
119 bcopy((char *)&call, bp, sizeof(int));
123 (void) strcpy(bp, first);
126 (void) strcpy(bp, last);
129 len = strlen(idnumber) + 1;
130 bcopy(idnumber, crypt_src, len);
132 bcopy(hashidnumber, crypt_src+len, 13);
134 des_string_to_key(hashidnumber, key);
135 des_key_sched(key, ks);
136 des_pcbc_encrypt(crypt_src, bp, len+13, ks, key, DES_ENCRYPT);
139 return do_call(buf, len, seq_no, login);
142 do_operation(first, last, idnumber, hashidnumber, data, opcode)
143 char *first, *last, *idnumber, *hashidnumber, *data;
147 int version = ntohl((u_long)1);
148 int call = ntohl(opcode);
151 register char *bp = buf;
154 char crypt_src[1024];
157 bcopy((char *)&version, bp, sizeof(int));
160 bcopy((char *)&seq_no, bp, sizeof(int));
164 bcopy((char *)&call, bp, sizeof(int));
168 (void) strcpy(bp, first);
171 (void) strcpy(bp, last);
174 len = strlen(idnumber) + 1;
177 bcopy(idnumber, crypt_src, len);
180 bcopy(hashidnumber, cbp, 14);
183 len = strlen(data) + 1;
184 bcopy(data, cbp, len);
187 len = cbp - crypt_src;
188 des_string_to_key(hashidnumber, key);
189 des_key_sched(key, ks);
190 des_pcbc_encrypt(crypt_src, bp, len, ks, key, 1);
191 len = ((len + 7) >> 3) << 3;
195 return do_call(buf, len, seq_no, 0);
199 grab_login(first, last, idnumber, hashidnumber, login)
200 char *first, *last, *idnumber, *hashidnumber, *login;
202 return(do_operation(first, last, idnumber, hashidnumber, login,
203 UREG_RESERVE_LOGIN));
206 enroll_login(first, last, idnumber, hashidnumber, login)
207 char *first, *last, *idnumber, *hashidnumber, *login;
209 return(do_operation(first, last, idnumber, hashidnumber, login,
213 set_password(first, last, idnumber, hashidnumber, password)
214 char *first, *last, *idnumber, *hashidnumber, *password;
216 return(do_operation(first, last, idnumber, hashidnumber, password,
220 get_krb(first, last, idnumber, hashidnumber, password)
221 char *first, *last, *idnumber, *hashidnumber, *password;
223 return(do_operation(first, last, idnumber, hashidnumber, password,
228 /* The handles the operations for secure passwords.
229 * To find out if a user has a secure instance, the newpasswd
230 * field is ignored (but must be a valid char *)
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
239 do_secure_operation(login, idnumber, passwd, newpasswd, opcode)
240 char *login, *idnumber, *passwd, *newpasswd;
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;
252 char *krb_get_phost(), *krb_realmofhost();
254 bcopy((char *)&version, bp, sizeof(int));
257 bcopy((char *)&seq_no, bp, sizeof(int));
261 bcopy((char *)&call, bp, sizeof(int));
265 /* put the login name in the firstname field */
266 (void) strcpy(bp, login);
269 /* the old lastname field */
270 (void) strcpy(bp, "");
273 /* don't overwrite existing ticket file */
274 (void) sprintf(tktstring, "/tmp/tkt_cpw_%d",getpid());
275 krb_set_tkt_string(tktstring);
277 /* get realm and canonizalized hostname of server */
278 realm = krb_realmofhost(host);
279 for (src = host, dst = hosti; *src && *src != '.'; src++)
281 *dst++ = tolower(*src);
288 /* get changepw tickets. We use this service because it's the
289 * only one that guarantees we used the password rather than a
290 * ticket granting ticket.
292 status = krb_get_pw_in_tkt(login, inst, realm,
293 "changepw", hosti, 5, passwd);
294 if (status) return (status + krb_err_base);
296 status = krb_mk_req(&cred, "changepw", hosti, realm, 0);
297 if (status) return (status + krb_err_base);
299 /* round up to word boundry */
300 bp = (char *)((((u_long)bp)+3)&0xfffffffc);
302 /* put the ticket in the packet */
304 cred.length = htonl(cred.length);
305 bcopy(&(cred), bp, sizeof(int)+len);
307 com_err("test", 0, "Cred: length %d", len);
308 for (i = 0; i < len; i += 16)
309 com_err("test", 0, " %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
310 cred.dat[i+0], cred.dat[i+1], cred.dat[i+2], cred.dat[i+3],
311 cred.dat[i+4], cred.dat[i+5], cred.dat[i+6], cred.dat[i+7],
312 cred.dat[i+8], cred.dat[i+9], cred.dat[i+10], cred.dat[i+11],
313 cred.dat[i+12], cred.dat[i+13], cred.dat[i+14], cred.dat[i+15]);
315 bp += sizeof(int) + len;
317 /* encrypt the data in the session key */
318 sprintf(data, "%s,%s", idnumber, newpasswd);
320 len = ((len + 7) >> 3) << 3;
322 status = krb_get_cred("changepw", hosti, realm, &creds);
324 bzero(data, strlen(data));
325 return (status + krb_err_base);
329 des_key_sched(creds.session, keys);
330 des_pcbc_encrypt(data, bp + sizeof(int), len, keys, creds.session, 1);
331 *((int *)bp) = htonl(len);
332 bzero(data, strlen(data));
334 bp += len + sizeof(int);
337 return do_call(buf, len, seq_no, 0);
341 static do_call(buf, len, seq_no, login)
347 struct timeval timeout;
354 if (write(reg_sock, buf, len) != len) return errno;
357 FD_SET(reg_sock, &set);
362 struct sockaddr_in sin;
363 int addrlen = sizeof(sin);
368 rtn = select(reg_sock+1, &set, (fd_set *)0, (fd_set *)0, &timeout);
371 else if (rtn < 0) return errno;
373 len = recvfrom(reg_sock, ibuf, BUFSIZ, 0, &sin, &addrlen);
374 if (len < 0) return errno;
375 if (len < 12) return UREG_BROKEN_PACKET;
376 bcopy(ibuf, (char *)&vno, sizeof(long));
377 vno = ntohl((u_long)vno);
378 if (vno != 1) continue;
379 bcopy(ibuf + 4, (char *)&sno, sizeof(long));
381 if (sno != seq_no) continue;
383 bcopy(ibuf + 8, (char *)&stat, sizeof(long));
384 stat = ntohl((u_long)stat);
385 if (login && len > 12) {
386 bcopy(ibuf+12, login, len-12);
387 login[len-12] = '\0';
392 } while (++retry < 10);