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