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