]> andersk Git - moira.git/blob - clients/userreg/reg_stubs.c
ff9bc2160a98d82d4e3351af7007b560fcf83eb2
[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
14
15 #include <mit-copyright.h>
16 #include <stdio.h>
17 #include <stdlib.h>
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>
24 #include <krb.h>
25 #include <krb_err.h>
26 #include <errno.h>
27 #include <moira.h>
28 #include <moira_site.h>
29 #include <hesiod.h>
30 #include "ureg_err.h"
31 #include "ureg_proto.h"
32 #include <string.h>
33 #include <ctype.h>
34
35 static int reg_sock = -1;
36 static int seq_no = 0;
37 static char *host;
38 extern errno;
39 #define UNKNOWN_HOST -1
40 #define UNKNOWN_SERVICE -2
41
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
48 int ureg_init(void)
49 {
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");
64 #ifdef HESIOD
65   if (!host || (strlen(host) == 0))
66     {
67       p = hes_resolve("registration", "sloc");
68       if (p)
69         host = *p;
70     }
71 #endif
72   if (!host || (strlen(host) == 0))
73     {
74       host = strsave(MOIRA_SERVER);
75       s = strchr(host, ':');
76       if (s)
77         *s = '\0';
78     }
79   hp = gethostbyname(host);
80   host = strsave(hp->h_name);
81   if (hp == NULL)
82     return UNKNOWN_HOST;
83
84   sp = getservbyname("sms_ureg", "udp");
85
86   if (sp == NULL)
87     return UNKNOWN_SERVICE;
88
89   close(reg_sock);
90   reg_sock = socket(AF_INET, SOCK_DGRAM, 0);
91   if (reg_sock < 0)
92     return errno;
93
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;
102 }
103
104 int verify_user(char *first, char *last, char *idnumber,
105                 char *hashidnumber, char *login)
106 {
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;
112   char *bp = buf;
113   int len;
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);
144 }
145
146 int do_operation(char *first, char *last, char *idnumber, char *hashidnumber,
147                  char *data, u_long opcode)
148 {
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;
154   char *bp = buf;
155   int len;
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;
176
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);
199 }
200
201 int grab_login(char *first, char *last, char *idnumber, char *hashidnumber,
202                char *login)
203 {
204   return do_operation(first, last, idnumber, hashidnumber, login,
205                       UREG_RESERVE_LOGIN);
206 }
207
208 int enroll_login(char *first, char *last, char *idnumber, char *hashidnumber,
209                  char *login)
210 {
211   return do_operation(first, last, idnumber, hashidnumber, login,
212                       UREG_SET_IDENT);
213 }
214
215 int set_password(char *first, char *last, char *idnumber, char *hashidnumber,
216                  char *password)
217 {
218   return do_operation(first, last, idnumber, hashidnumber, password,
219                       UREG_SET_PASSWORD);
220 }
221
222 int get_krb(char *first, char *last, char *idnumber, char *hashidnumber,
223             char *password)
224 {
225   return do_operation(first, last, idnumber, hashidnumber, password,
226                       UREG_GET_KRB);
227 }
228
229
230 /* The handles the operations for secure passwords.
231  * To find out if a user has a secure instance, the newpasswd
232  * field is ignored (but must be a valid char *)
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
241 int do_secure_operation(char *login, char *idnumber, char *passwd,
242                         char *newpasswd, u_long opcode)
243 {
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     {
281       if (isupper(*src))
282         *dst++ = tolower(*src);
283       else
284         *dst++ = *src;
285     }
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();
322
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));
327
328   bp += len + sizeof(int);
329
330   len = bp - buf;
331   return do_call(buf, len, seq_no, 0);
332 }
333
334 int do_call(char *buf, int len, int seq_no, char *login)
335 {
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 }
This page took 0.055377 seconds and 3 git commands to generate.