3 * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
4 * For copying and distribution information, please see the file
8 #include <mit-copyright.h>
10 #include <moira_site.h>
11 #include "ureg_proto.h"
13 #include <sys/types.h>
14 #include <sys/socket.h>
17 #include <netinet/in.h>
33 int do_operation(char *first, char *last, char *idnumber, char *hashidnumber,
34 char *data, u_long opcode);
35 int do_secure_operation(char *login, char *idnumber, char *passwd,
36 char *newpasswd, u_long opcode);
37 int do_call(char *buf, int len, int seq_no, char *login);
39 char *krb_realmofhost(char *);
41 static int reg_sock = -1;
42 static int seq_no = 0;
44 #define UNKNOWN_HOST -1
45 #define UNKNOWN_SERVICE -2
48 #define FD_ZERO(p) ((p)->fds_bits[0] = 0)
49 #define FD_SET(n, p) ((p)->fds_bits[0] |= (1 << (n)))
50 #define FD_ISSET(n, p) ((p)->fds_bits[0] & (1 << (n)))
58 struct sockaddr_in s_in;
60 initialize_ureg_error_table();
61 initialize_krb_error_table();
62 initialize_sms_error_table();
63 initialize_kadm_error_table();
68 host = getenv("REGSERVER");
70 if (!host || (strlen(host) == 0))
72 p = hes_resolve("registration", "sloc");
77 if (!host || (strlen(host) == 0))
79 host = strdup(MOIRA_SERVER);
80 s = strchr(host, ':');
84 hp = gethostbyname(host);
85 host = strdup(hp->h_name);
89 sp = getservbyname("moira_ureg", "udp");
92 return UNKNOWN_SERVICE;
95 reg_sock = socket(AF_INET, SOCK_DGRAM, 0);
99 memset(&s_in, 0, sizeof(s_in));
100 s_in.sin_port = sp->s_port;
101 memcpy(&s_in.sin_addr, hp->h_addr, sizeof(struct in_addr));
102 s_in.sin_family = AF_INET;
104 if (connect(reg_sock, (struct sockaddr *)&s_in, sizeof(s_in)) < 0)
109 int verify_user(char *first, char *last, char *idnumber,
110 char *hashidnumber, char *login)
113 int version = ntohl((u_long)1);
114 int call = ntohl((u_long)UREG_VERIFY_USER);
119 char crypt_src[1024];
121 memcpy(bp, &version, sizeof(int));
124 memcpy(bp, &seq_no, sizeof(int));
128 memcpy(bp, &call, sizeof(int));
133 bp += strlen(bp) + 1;
136 bp += strlen(bp) + 1;
138 len = strlen(idnumber) + 1;
139 memcpy(crypt_src, idnumber, len);
141 memcpy(crypt_src + len, hashidnumber, 13);
143 des_string_to_key(hashidnumber, key);
144 des_key_sched(key, ks);
145 des_pcbc_encrypt(crypt_src, bp, len + 13, ks, key, DES_ENCRYPT);
148 return do_call(buf, len, seq_no, login);
151 int do_operation(char *first, char *last, char *idnumber, char *hashidnumber,
152 char *data, u_long opcode)
155 int version = ntohl((u_long)1);
156 int call = ntohl(opcode);
162 char crypt_src[1024];
165 memcpy(bp, &version, sizeof(int));
168 memcpy(bp, &seq_no, sizeof(int));
172 memcpy(bp, &call, sizeof(int));
177 bp += strlen(bp) + 1;
180 bp += strlen(bp) + 1;
182 len = strlen(idnumber) + 1;
185 memcpy(crypt_src, idnumber, len);
188 memcpy(cbp, hashidnumber, 14);
191 len = strlen(data) + 1;
192 memcpy(cbp, data, len);
195 len = cbp - crypt_src;
196 des_string_to_key(hashidnumber, key);
197 des_key_sched(key, ks);
198 des_pcbc_encrypt(crypt_src, bp, len, ks, key, 1);
199 len = ((len + 7) >> 3) << 3;
203 return do_call(buf, len, seq_no, 0);
206 int grab_login(char *first, char *last, char *idnumber, char *hashidnumber,
209 return do_operation(first, last, idnumber, hashidnumber, login,
213 int enroll_login(char *first, char *last, char *idnumber, char *hashidnumber,
216 return do_operation(first, last, idnumber, hashidnumber, login,
220 int set_password(char *first, char *last, char *idnumber, char *hashidnumber,
223 return do_operation(first, last, idnumber, hashidnumber, password,
227 int get_krb(char *first, char *last, char *idnumber, char *hashidnumber,
230 return do_operation(first, last, idnumber, hashidnumber, password,
235 /* The handles the operations for secure passwords.
236 * To find out if a user has a secure instance, the newpasswd
237 * field is ignored (but must be a valid char *)
238 * and the opcode = UREG_GET_SECURE need to be specified (but the
239 * other strings must be valid char*'s). This will return
240 * UREG_ALREADY_REGISTERED if it is set, or SUCCESS if not.
241 * To set the password, fill in the rest of the fields, and
242 * use opcode = UREG_SET_SECURE. This returns SUCCESS or any number
246 int do_secure_operation(char *login, char *idnumber, char *passwd,
247 char *newpasswd, u_long opcode)
249 char buf[1500], data[128], tktstring[128];
250 int version = ntohl((u_long)1);
251 int call = ntohl(opcode);
252 char inst[INST_SZ], hosti[INST_SZ];
253 char *bp = buf, *src, *dst, *realm;
259 memmove(bp, &version, sizeof(int));
262 memmove(bp, &seq_no, sizeof(int));
265 memmove(bp, &call, sizeof(int));
269 /* put the login name in the firstname field */
271 bp += strlen(bp) + 1;
273 /* the old lastname field */
275 bp += strlen(bp) + 1;
277 /* don't overwrite existing ticket file */
278 sprintf(tktstring, "/tmp/tkt_cpw_%ld", (long)getpid());
279 krb_set_tkt_string(tktstring);
281 /* get realm and canonizalized hostname of server */
282 realm = krb_realmofhost(host);
283 for (src = host, dst = hosti; *src && *src != '.'; src++)
286 *dst++ = tolower(*src);
293 /* get changepw tickets. We use this service because it's the
294 * only one that guarantees we used the password rather than a
295 * ticket granting ticket.
297 status = krb_get_pw_in_tkt(login, inst, realm, "changepw", hosti, 5, passwd);
299 return status + krb_err_base;
301 status = krb_mk_req(&cred, "changepw", hosti, realm, 0);
303 return status + krb_err_base;
305 /* round up to word boundry */
306 bp = (char *)((((u_long)bp) + 3) & 0xfffffffc);
308 /* put the ticket in the packet */
310 cred.length = htonl(cred.length);
311 memmove(bp, &(cred), sizeof(int) + len);
312 bp += sizeof(int) + len;
314 /* encrypt the data in the session key */
315 sprintf(data, "%s,%s", idnumber, newpasswd);
317 len = ((len + 7) >> 3) << 3;
319 status = krb_get_cred("changepw", hosti, realm, &creds);
322 memset(data, 0, strlen(data));
323 return status + krb_err_base;
327 des_key_sched(creds.session, keys);
328 des_pcbc_encrypt(data, bp + sizeof(int), len, keys, creds.session, 1);
329 *((int *)bp) = htonl(len);
330 memset(data, 0, strlen(data));
332 bp += len + sizeof(int);
335 return do_call(buf, len, seq_no, 0);
338 int do_call(char *buf, int len, int seq_no, char *login)
340 struct timeval timeout;
348 if (write(reg_sock, buf, len) != len)
352 FD_SET(reg_sock, &set);
358 struct sockaddr_in s_in;
359 int addrlen = sizeof(s_in);
364 rtn = select(reg_sock + 1, &set, NULL, NULL, &timeout);
370 len = recvfrom(reg_sock, ibuf, BUFSIZ, 0,
371 (struct sockaddr *)&s_in, &addrlen);
375 return UREG_BROKEN_PACKET;
376 memcpy(&vno, ibuf, sizeof(long));
377 vno = ntohl((u_long)vno);
380 memcpy(&sno, ibuf + 4, sizeof(long));
385 memcpy(&stat, ibuf + 8, sizeof(long));
386 stat = ntohl((u_long)stat);
387 if (login && len > 12)
389 memcpy(login, ibuf + 12, len - 12);
390 login[len - 12] = '\0';
398 while (++retry < 10);