]> andersk Git - moira.git/blob - clients/userreg/reg_stubs.c
posixification from miki
[moira.git] / clients / userreg / reg_stubs.c
1 /*
2  *      $Source$
3  *      $Author$
4  *      $Header$
5  *
6  *  (c) Copyright 1988 by the Massachusetts Institute of Technology.
7  *  For copying and distribution information, please see the file
8  *  <mit-copyright.h>.
9  */
10
11 #ifndef lint
12 static char *rcsid_reg_stubs_c = "$Header$";
13 #endif lint
14
15 #include <mit-copyright.h>
16 #include <stdio.h>
17 #include <sys/types.h>
18 #include <sys/time.h>
19 #include <sys/socket.h>
20 #ifdef _AIX_SOURCE
21 #include <sys/select.h>
22 #endif
23 #include <netinet/in.h>
24 #include <netdb.h>
25 #include <des.h>
26 #include <krb.h>
27 #include <krb_err.h>
28 #include <errno.h>
29 #include <moira.h>
30 #include <moira_site.h>
31 #include "ureg_err.h"
32 #include "ureg_proto.h"
33 #include <string.h>
34 #include <ctype.h>
35
36 static int reg_sock = -1;
37 static int seq_no = 0;
38 static char *host;
39 extern errno;
40 #define UNKNOWN_HOST -1
41 #define UNKNOWN_SERVICE -2
42
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
49 ureg_init()
50 {
51     struct servent *sp;
52     char **p, *s;
53     struct hostent *hp;
54     struct sockaddr_in s_in;
55     extern char *getenv(), **hes_resolve();
56     
57     initialize_ureg_error_table();
58     initialize_krb_error_table(); 
59     initialize_sms_error_table();
60     initialize_kadm_error_table();
61    
62     seq_no = getpid();
63
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)) {
73         host = strsave(MOIRA_SERVER);
74         s = strchr(host, ':');
75         if (s) *s = 0;
76     }
77     hp = gethostbyname(host);
78     host = strsave(hp->h_name);
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
89     memset((char *)&s_in, 0, sizeof(s_in));
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;
93
94     if (connect(reg_sock, &s_in, sizeof(s_in)) < 0)
95         return errno;
96     return 0;
97 }
98
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);
106     des_cblock key;
107     des_key_schedule ks;
108     register char *bp = buf;
109     register int len;
110     char crypt_src[1024];
111     
112     memcpy(bp, (char *)&version, sizeof(int));
113     bp += sizeof(int);
114     seq_no++;
115     memcpy(bp, (char *)&seq_no, sizeof(int));
116
117     bp += sizeof(int);
118
119     memcpy(bp, (char *)&call, sizeof(int));
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;
130     memcpy(crypt_src, idnumber, len);
131
132     memcpy(crypt_src+len, hashidnumber, 13);
133
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);
137     bp += len+14+8;
138     len = bp - buf;
139     return do_call(buf, len, seq_no, login);
140 }
141
142 do_operation(first, last, idnumber, hashidnumber, data, opcode)
143     char *first, *last, *idnumber, *hashidnumber, *data;
144     u_long opcode;
145 {
146     char buf[1024];
147     int version = ntohl((u_long)1);
148     int call = ntohl(opcode);
149     des_cblock key;
150     des_key_schedule ks;
151     register char *bp = buf;
152     register int len;
153     
154     char crypt_src[1024];
155     char *cbp;
156     
157     memcpy(bp, (char *)&version, sizeof(int));
158     bp += sizeof(int);
159     seq_no++;
160     memcpy(bp, (char *)&seq_no, sizeof(int));
161
162     bp += sizeof(int);
163
164     memcpy(bp, (char *)&call, sizeof(int));
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     
177     memcpy(crypt_src, idnumber, len);
178     cbp += len;
179     
180     memcpy(cbp, hashidnumber, 14);
181     cbp += 14;
182     
183     len = strlen(data) + 1;
184     memcpy(cbp, data, len);
185     cbp += len;
186
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;
192     bp += len;
193     
194     len = bp - buf;
195     return do_call(buf, len, seq_no, 0);
196
197 }
198
199 grab_login(first, last, idnumber, hashidnumber, login)
200     char *first, *last, *idnumber, *hashidnumber, *login;
201 {
202     return(do_operation(first, last, idnumber, hashidnumber, login,
203                         UREG_RESERVE_LOGIN));
204 }
205
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 }
212
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 }
219
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));
225 }
226
227
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
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();
253 #ifdef POSIX    
254     memmove(bp, (char *)&version, sizeof(int));
255 #else
256     bcopy((char *)&version, bp, sizeof(int));
257 #endif
258     bp += sizeof(int);
259     seq_no++;
260 #ifdef POSIX
261     memmove(bp, (char *)&seq_no, sizeof(int));
262 #else
263     bcopy((char *)&seq_no, bp, sizeof(int));
264 #endif
265
266     bp += sizeof(int);
267 #ifdef POSIX
268     memmove(bp, (char *)&call,  sizeof(int));
269 #else
270     bcopy((char *)&call, bp, sizeof(int));
271 #endif
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);
304     if (status) return (status + krb_err_base);
305
306     status = krb_mk_req(&cred, "changepw", hosti, realm, 0);
307     if (status) return (status + krb_err_base);
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);
315 #ifdef POSIX
316     memmove(bp, &(cred), sizeof(int)+len);
317 #else
318     bcopy(&(cred), bp, sizeof(int)+len);
319 #endif
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) {
338         memset(data, 0, strlen(data));
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);
346     memset(data, 0, strlen(data));
347
348     bp += len + sizeof(int);
349     
350     len = bp - buf;
351     return do_call(buf, len, seq_no, 0);
352
353 }
354
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);
372         timeout.tv_sec = 30;
373         timeout.tv_usec = 0;
374         do {
375             int rtn;
376             struct sockaddr_in s_in;
377             int addrlen = sizeof(s_in);
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         
387             len = recvfrom(reg_sock, ibuf, BUFSIZ, 0, &s_in, &addrlen);
388             if (len < 0) return errno;
389             if (len < 12) return UREG_BROKEN_PACKET;
390             memcpy((char *)&vno, ibuf, sizeof(long));
391             vno = ntohl((u_long)vno);
392             if (vno != 1) continue;
393             memcpy((char *)&sno, ibuf + 4, sizeof(long));
394
395             if (sno != seq_no) continue;
396
397             memcpy((char *)&stat, ibuf + 8, sizeof(long));
398             stat = ntohl((u_long)stat);
399             if (login && len > 12) {
400                 memcpy(login, ibuf+12, len-12);
401                 login[len-12] = '\0';
402             } else if (login)
403                 *login = '\0';
404             return stat;
405         } while (1);
406     } while (++retry < 10);
407     return ETIMEDOUT;
408 }    
This page took 2.452995 seconds and 5 git commands to generate.