]> andersk Git - moira.git/blame - reg_svr/reg_svr.pc
Quick and dirty fix: Don't call register_user() for LINCOLN users with
[moira.git] / reg_svr / reg_svr.pc
CommitLineData
b50f996d 1/* $Id$
2 *
3 * Server for user registration with Moira and Kerberos.
4 *
5 * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
6 * For copying and distribution information, please see the file
7 * <mit-copyright.h>.
8 */
9
10#include <mit-copyright.h>
11#include <moira.h>
12#include <mr_private.h>
13#include <moira_schema.h>
14#include <moira_site.h>
15#include "reg_svr.h"
16
17#include <sys/types.h>
18#include <sys/socket.h>
19#include <sys/stat.h>
20#include <sys/time.h>
21#include <sys/utsname.h>
22
23#include <netinet/in.h>
24#include <netdb.h>
25
26#include <ctype.h>
27#include <errno.h>
28#include <signal.h>
29#include <stdarg.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <unistd.h>
34
35#include <com_err.h>
36#include <krb.h>
37
38EXEC SQL INCLUDE sqlca;
39
40RCSID("$Header$");
41
42char *whoami, *hostname, *shorthostname;
43
44char *find_usernames(char *first, char *middle, char *last);
45void fixname(char *name);
46int register_user(int uid, char *username);
47void mr_com_err(const char *whoami, long code, const char *fmt, va_list pvar);
48void sigshut(int);
49
50reg_client *cl = NULL;
51enum { RS_RUNNING, RS_SLEEPING, RS_EXITING } state = RS_RUNNING;
52
53int main(int argc, char **argv)
54{
55 int listener, nfds, i, clientid = 0;
56 fd_set readfds, xreadfds;
57 reg_client *clients;
58 int nclients, clientssize;
59 long status;
60 char *db = "moira";
61 struct utsname uts;
62 struct hostent *h;
63 struct sigaction sa;
64 struct stat st;
65
66 whoami = strrchr(argv[0], '/');
67 whoami = whoami ? whoami + 1 : argv[0];
68
69 set_com_err_hook(mr_com_err);
70
71 /* Read keys */
72 if (!read_rsa_key())
73 {
74 com_err(whoami, errno, "reading RSA key");
75 exit(1);
76 }
77 if (!read_hmac_key())
78 {
79 com_err(whoami, errno, "reading HMAC key");
80 exit(1);
81 }
82
83 /* Read error messages */
84 if (!read_errors())
85 {
86 com_err(whoami, errno, "reading error messages");
87 exit(1);
88 }
89
90 /* Connect to database */
91 EXEC SQL CONNECT :db IDENTIFIED BY :db;
92 if (sqlca.sqlcode)
93 {
94 char err_msg[256];
95 int bufsize = 256, msglength = 0;
96
97 sqlglm(err_msg, &bufsize, &msglength);
98 err_msg[msglength] = 0;
99 com_err(whoami, 0, "SQL error connecting to DBMS:\n%s", err_msg);
100 exit(1);
101 }
102
103 /* Get my hostname */
104 uname(&uts);
105 h = gethostbyname(uts.nodename);
106 if (!h)
107 {
108 com_err(whoami, 0, "Couldn't resolve hostname %s", uts.nodename);
109 exit(1);
110 }
111 hostname = lowercase(xstrdup(h->h_name));
112 shorthostname = xstrdup(hostname);
113 if (strchr(shorthostname, '.'))
114 *strchr(shorthostname, '.') = '\0';
115
116 /* Initialize kerberos */
117 status = init_kerberos();
118 if (status)
119 {
120 com_err(whoami, status, "initializing kerberos library");
121 exit(1);
122 }
123
124 /* Set up listening socket. */
125 listener = mr_listen("moira_ureg");
126 if (listener < 0)
127 {
128 com_err(whoami, errno, "couldn't create listening socket");
129 exit(1);
130 }
131 FD_ZERO(&xreadfds);
132 FD_SET(listener, &xreadfds);
133 nfds = listener + 1;
134
135 /* Initialize client array. */
136 nclients = 0;
137 clientssize = 5;
138 clients = malloc(clientssize * sizeof(reg_client));
139 if (!clients)
140 {
141 com_err(whoami, errno, "creating client array");
142 exit(1);
143 }
144
145 /* Set up signal handlers */
146 sa.sa_flags = 0;
147 sigemptyset(&sa.sa_mask);
148 sa.sa_handler = sigshut;
149 sigaction(SIGTERM, &sa, NULL);
150 sigaction(SIGINT, &sa, NULL);
151 sigaction(SIGHUP, &sa, NULL);
152 sa.sa_handler = SIG_IGN;
153 sigaction(SIGPIPE, &sa, NULL);
154
155 com_err(whoami, 0, "started (pid %d)", getpid());
156 com_err(whoami, 0, rcsid);
157
158 /* Main loop */
159 while (state != RS_EXITING)
160 {
161 if (state == RS_RUNNING && stat(MOIRA_MOTD_FILE, &st) == 0)
162 {
9dcee057 163 state = RS_SLEEPING;
b50f996d 164 com_err(whoami, 0, "found motd. reg_svr is sleeping");
165 }
166 else if (state == RS_SLEEPING && stat(MOIRA_MOTD_FILE, &st) == -1)
167 {
9dcee057 168 state = RS_RUNNING;
b50f996d 169 com_err(whoami, 0, "motd gone. reg_svr is running");
170 }
171
172 memcpy(&readfds, &xreadfds, sizeof(readfds));
173 if (select(nfds, &readfds, NULL, NULL, NULL) == -1)
174 {
175 if (errno != EINTR)
176 com_err(whoami, errno, "in select");
177 continue;
178 }
179
180 if (FD_ISSET(listener, &readfds))
181 {
182 int newconn, addrlen = sizeof(struct sockaddr_in);
183 struct sockaddr_in addr;
184
185 newconn = accept(listener, (struct sockaddr *)&addr, &addrlen);
186 if (newconn < 0)
187 com_err(whoami, errno, "accepting new connection");
188 else
189 {
190 nclients++;
191 if (nclients > clientssize)
192 {
193 clientssize = 2 * clientssize;
194 clients = xrealloc(clients, clientssize *
195 sizeof(reg_client));
196 }
197
198 cl = &clients[nclients - 1];
199 memset(cl, 0, sizeof(reg_client));
200 cl->fd = newconn;
201 cl->lastmod = time(NULL);
202 cl->clientid = ++clientid;
203 cl->random = init_rand(cl);
204 FD_SET(newconn, &xreadfds);
205 if (newconn >= nfds)
206 nfds = newconn + 1;
207
208 com_err(whoami, 0,
209 "New connection from %s port %d (now %d client%s)",
210 inet_ntoa(addr.sin_addr), (int)ntohs(addr.sin_port),
211 nclients, nclients != 1 ? "s" : "");
212 }
213 }
214
215 for (i = 0; i < nclients; i++)
216 {
217 cl = &clients[i];
218 if (FD_ISSET(cl->fd, &readfds))
219 {
220 cl->lastmod = time(NULL);
221 if (!cl->buf)
222 {
223 /* We're just starting */
224 cl->buf = malloc(3);
225 if (!cl->buf)
226 {
227 com_err(whoami, errno, "allocating read buffer");
228 reply(cl, INTERNAL_ERROR, "INIT", "c", NULL,
229 "Out of memory");
230 goto reap;
231 }
232 cl->nread = 0;
233 }
234
235 if (cl->nread < 3)
236 {
237 /* We haven't read the length byte yet... */
238 cl->nread += read(cl->fd, cl->buf + cl->nread,
239 3 - cl->nread);
240 if (cl->nread == 3)
241 {
242 cl->nmax = cl->buf[1] * 256 + cl->buf[2] + 3;
243 cl->buf = realloc(cl->buf, cl->nmax + 3);
244 if (!cl->buf)
245 {
246 com_err(whoami, errno, "reallocating read buffer");
247 reply(cl, INTERNAL_ERROR, "INIT", "c", NULL,
248 "Out of memory");
249 goto reap;
250 }
251 }
252 else if (cl->nread == 0)
253 {
254 /* client has closed connection. setting
255 lastmod will cause it to be reaped */
256 cl->lastmod = 0;
257 }
258 }
259 else
260 {
261 /* We know how long the packet is supposed to be */
262 cl->nread += read(cl->fd, cl->buf + cl->nread,
263 cl->nmax - cl->nread);
264 if (cl->nread == cl->nmax)
265 {
266 parse_packet(cl, cl->buf[0], cl->nread - 3, cl->buf + 3,
267 state == RS_SLEEPING);
268 free(cl->buf);
269 cl->buf = NULL;
270 }
271 }
272 }
273
274 reap:
275 if (cl->lastmod < time(NULL) - TIMEOUT)
276 {
277 com_err(whoami, 0, "Closed connection. (now %d client%s)",
278 nclients - 1, nclients != 2 ? "s" : "");
279 shutdown(cl->fd, 2);
280 close(cl->fd);
281 FD_CLR(cl->fd, &xreadfds);
282 free(cl->buf);
283 free(cl->id);
284 free(cl->username);
285 free(cl->suggestions);
286 free(cl->random);
287 clients[i] = clients[--nclients];
288 i--;
289 }
290 }
291 cl = NULL;
292 }
293 com_err(whoami, 0, "Exiting.");
294}
295
296void RIFO(reg_client *rc, int argc, char **argv)
297{
298 EXEC SQL BEGIN DECLARE SECTION;
299 char *ufirst, *umiddle, *ulast, *id;
300 char login[USERS_LOGIN_SIZE], first[USERS_FIRST_SIZE];
301 char middle[USERS_MIDDLE_SIZE], last[USERS_LAST_SIZE];
302 char fullname[USERS_FIRST_SIZE + USERS_MIDDLE_SIZE + USERS_LAST_SIZE];
303 char class[USERS_TYPE_SIZE];
6531b2d6 304 int uid, status, secure, sqlstatus, string_id;
b50f996d 305 EXEC SQL END DECLARE SECTION;
306
307 if (rc->uid || argc != 4)
308 {
309 reply(rc, PROTOCOL_ERROR, "INIT", "c", NULL);
310 return;
311 }
312
313 ufirst = argv[0];
314 umiddle = argv[1];
315 ulast = argv[2];
316 id = argv[3];
317
318 /* "ORDER BY status" so that if there's both a matching state 0 entry
319 and a matching state 3 entry, we'll get the former. */
320 EXEC SQL DECLARE csr_id CURSOR FOR
321 SELECT login, unix_uid, status, secure, first, middle, last, type
322 FROM users WHERE clearid = :id ORDER BY status;
323 EXEC SQL OPEN csr_id;
324 while (1)
325 {
326 EXEC SQL FETCH csr_id INTO :login, :uid, :status,
327 :secure, :first, :middle, :last, :class;
328 if (sqlca.sqlcode)
329 break;
330 strtrim(login);
331 strtrim(first);
332 strtrim(middle);
333 strtrim(last);
334 strtrim(class);
335
336 /* Check names, allowing for the possibility that Moira and the
337 user might have them split up differently. eg, Mary/Ann/Singleton
338 vs. Mary Ann/Singleton. */
339 if (strcasecmp(last, ulast) && strncasecmp(last, ulast, strlen(last)) &&
340 strncasecmp(last, ulast, strlen(ulast)))
341 continue;
342 if (strlen(last) > 3 && strlen(ulast) < 3)
343 continue;
344 if (strcasecmp(first, ufirst) &&
345 strncasecmp(first, ufirst, strlen(first)) &&
346 strncasecmp(first, ufirst, strlen(ufirst)))
347 continue;
348 if (strlen(first) > 3 && strlen(ufirst) < 3)
349 continue;
350 /* Ignore the middle name since Moira doesn't have those reliably */
351 break;
352 }
353 sqlstatus = sqlca.sqlcode;
354 EXEC SQL CLOSE csr_id;
355
356 if (sqlstatus)
357 {
358 reply(rc, NOT_FOUND_IN_DATABASE, "GETN", "d", NULL);
359 return;
360 }
361
362 switch (status)
363 {
364 case US_REGISTERED:
365 case US_ENROLLED:
366 case US_ENROLL_NOT_ALLOWED:
367 reply(rc, ALREADY_REGISTERED, "INIT", "c", NULL, login);
368 return;
369
370 case US_DELETED:
371 reply(rc, ACCOUNT_DELETED, "INIT", "c", NULL, login);
372 return;
373
374 case US_NOT_ALLOWED:
375 reply(rc, NOT_ELIGIBLE, "INIT", "c", NULL);
376 return;
377
378 default:
379 break;
380 }
381
382 rc->uid = uid;
383 sprintf(fullname, "%s %s%s%s", first, middle, *middle ? " " : "", last);
384 if (!strcmp(class, "MITS"))
385 strcpy(class, "STAFF");
386 if (secure == 1)
387 {
388 rc->id = strdup(id);
389 if (!rc->id)
390 {
391 com_err(whoami, errno, "in RIFO");
392 reply(rc, INTERNAL_ERROR, "INIT", "c", NULL, "Out of memory");
393 return;
394 }
395 }
396 if (*login != '#')
397 {
398 rc->reserved_username = 1;
399 rc->username = strdup(login);
400 if (!rc->username)
401 {
402 com_err(whoami, errno, "in RIFO");
403 reply(rc, INTERNAL_ERROR, "INIT", "c", NULL, "Out of memory");
404 return;
405 }
406 }
407 else
408 {
409 rc->suggestions = find_usernames(first, middle, last);
8dc13a24 410 if (!rc->suggestions && errno)
b50f996d 411 {
412 com_err(whoami, errno, "in RIFO");
8dc13a24 413 reply(rc, INTERNAL_ERROR, "INIT", "c", NULL, error_message(errno));
b50f996d 414 return;
415 }
416 }
417
418 if (rc->id)
419 reply(rc, FOUND, "GETW", "c", NULL, fullname, class);
420 else if (!rc->username)
421 reply(rc, FOUND, "GETL", "c", rc->suggestions, fullname, class);
422 else
78b14dbc 423 {
424 if (status == US_NO_LOGIN_YET)
425 {
426 status = check_kerberos(login);
427 if (status == MR_SUCCESS)
6531b2d6 428 if (!strcmp(class, "LINCOLN"))
429 {
430 EXEC SQL SELECT string_id INTO :string_id FROM strings
431 WHERE string = 'LINCOLN: no pobox or filesys';
432 EXEC SQL UPDATE users SET comments = :string_id
433 WHERE login = :login;
434 }
435 else
436 status = register_user(rc->uid, login);
78b14dbc 437 if (status == MR_IN_USE)
438 {
439 reply(rc, RESERVED_USERNAME_UNAVAILABLE, "INIT", "c", NULL,
440 rc->username);
441 return;
442 }
443 else if (status == MR_DOWN)
444 {
445 reply(rc, DATABASE_CLOSED, "INIT", "c", NULL);
446 return;
447 }
448 else if (status != MR_SUCCESS)
449 {
450 reply(rc, INTERNAL_ERROR, "INIT", "c", NULL,
451 error_message(status));
452 return;
453 }
454 }
455 reply(rc, FORCED_USERNAME, "GETP", "c", NULL, rc->username);
456 }
b50f996d 457}
458
459void SWRD(reg_client *rc, int argc, char **argv)
460{
461 char *words[6];
462 int i;
463
464 if (!rc->id || argc != 6)
465 {
466 reply(rc, PROTOCOL_ERROR, "INIT", "c", NULL);
467 return;
468 }
469
470 getwordlist(rc->id, words);
471 for (i = 0; i < 6; i++)
472 {
473 if (strcasecmp(strtrim(argv[i]), words[i]))
474 break;
475 }
476 if (i != 6)
477 {
478 reply(rc, BAD_SIX_WORDS, "GETW", "d", NULL);
479 return;
480 }
481
482 free(rc->id);
483 rc->id = NULL;
484 if (!rc->username)
485 reply(rc, NO_MESSAGE, "GETL", "c", rc->suggestions);
486 else
487 reply(rc, FORCED_USERNAME, "GETP", "c", NULL, rc->username);
488}
489
490void LOGN(reg_client *rc, int argc, char **argv)
491{
492 int i;
493 char *login;
494 long status;
495
496 if (!rc->uid || rc->id || rc->username || argc != 1)
497 {
498 reply(rc, PROTOCOL_ERROR, "INIT", "c", NULL);
499 return;
500 }
501
502 login = argv[0];
503
504 /* make sure someone's not trying to overrun reply */
505 if (strlen(login) > 100)
506 {
507 com_err(whoami, 0, "Buffer overrun attempted? Closing connection");
508 rc->lastmod = 0;
509 return;
510 }
511
512 if ((strlen(login) < 3) || (strlen(login) > USERS_LOGIN_SIZE - 1) ||
513 (login[0] == '_') || isdigit(login[0]))
514 {
515 reply(rc, BAD_USERNAME, "GETL", "c", rc->suggestions, login,
516 3, USERS_LOGIN_SIZE - 1);
517 return;
518 }
519
520 for (i = 0; i < strlen(login); i++)
521 {
522 if (!islower(login[i]) && !isdigit(login[i]) && (login[i] != '_'))
523 {
524 reply(rc, BAD_USERNAME, "GETL", "c", rc->suggestions, login,
525 3, USERS_LOGIN_SIZE - 1);
526 return;
527 }
528 }
529
530 status = check_kerberos(login);
531 if (status == MR_SUCCESS)
532 status = register_user(rc->uid, login);
533
534 if (status == MR_IN_USE)
535 {
536 if (rc->reserved_username)
537 {
538 reply(rc, RESERVED_USERNAME_UNAVAILABLE, "INIT", "c", NULL,
539 rc->username);
540 return;
541 }
542 reply(rc, USERNAME_UNAVAILABLE, "GETL", "c", rc->suggestions);
543 return;
544 }
545 else if (status == MR_DOWN)
546 {
547 reply(rc, DATABASE_CLOSED, "INIT", "c", NULL);
548 return;
549 }
550 else if (status != MR_SUCCESS)
551 {
552 reply(rc, INTERNAL_ERROR, "INIT", "c", NULL, error_message(status));
553 return;
554 }
555
556 rc->username = strdup(login);
557 if (!rc->username)
558 {
559 com_err(whoami, errno, "in LOGN");
560 reply(rc, INTERNAL_ERROR, "INIT", "c", NULL, "Out of memory");
561 return;
562 }
563 reply(rc, USERNAME_OK, "GETP", "c", NULL, login);
564}
565
566int ctypes[256] = {
567 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ^@ - ^O */
568 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ^P - ^_ */
569 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* SPACE - / */
570 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, /* 0 - ? */
571 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* : - O */
572 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, /* P - _ */
573 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, /* ` - o */
574 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, /* p - ^? */
575 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
576 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
577 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
578 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
579 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
580 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
581 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
582 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
583};
584
585void PSWD(reg_client *rc, int argc, char **argv)
586{
587 long status;
588 char *password = argv[0], *p;
589 EXEC SQL BEGIN DECLARE SECTION;
590 char *login = rc->username;
591 EXEC SQL END DECLARE SECTION;
592
593 if (!rc->username || rc->id || argc != 1)
594 {
595 reply(rc, PROTOCOL_ERROR, "INIT", "c", NULL);
596 return;
597 }
598
599 /* password quality checking */
600 if (strlen(password) < 4)
601 {
602 reply(rc, PASSWORD_SHORT, "GETP", "c", NULL);
603 return;
604 }
605
606 if (strlen(password) < 7)
607 {
608 for (p = password + 1; *p; p++)
609 {
610 if (ctypes[*p] != ctypes[*(p - 1)])
611 break;
612 }
613 if (!*p)
614 {
615 reply(rc, PASSWORD_SIMPLE, "GETP", "c", NULL);
616 return;
617 }
618 }
619
620 if (!strcasecmp(password, "GykoR-66") ||
621 !strcasecmp(password, "slaRooBey") ||
622 !strcasecmp(password, "krang-its") ||
623 !strcasecmp(password, "2HotPeetzas") ||
624 !strcasecmp(password, "ItzAGurl"))
625 {
626 reply(rc, PASSWORD_SAMPLE, "GETP", "c", NULL);
627 return;
628 }
629
630 status = register_kerberos(rc->username, password);
9c0c1480 631 if (status == MR_QUALITY)
632 {
633 reply(rc, PASSWORD_SIMPLE, "GETP", "c", NULL);
634 return;
635 }
636 else if (status == MR_IN_USE)
b50f996d 637 {
638 reply(rc, RESERVED_USERNAME_UNAVAILABLE, "INIT", "c", NULL,
639 rc->username);
640 return;
641 }
642 else if (status)
643 {
644 com_err(whoami, status, "registering username with Kerberos");
645 reply(rc, KADM_ERROR, "INIT", "c", NULL, error_message(status));
646 return;
647 }
648 EXEC SQL UPDATE users SET status = 1 WHERE login = :login;
649 EXEC SQL COMMIT;
650
651 reply(rc, DONE, "INIT", "c", NULL, rc->username);
652}
653
654void QUIT(reg_client *rc, int argc, char **argv)
655{
656}
657
658/* Register a user in Moira */
659int register_user(int uid, char *username)
660{
661 char uidbuf[10], *qargv[3], *motd = NULL;
662 long status;
663
664 status = mr_connect(hostname);
665 if (status)
666 return status;
667
668 status = mr_motd(&motd);
669 if (status || motd)
670 {
671 mr_disconnect();
672 return MR_DOWN;
673 }
674
675 status = krb_get_svc_in_tkt(REG_SVR_PRINCIPAL, REG_SVR_INSTANCE,
676 krb_realmofhost(hostname), MOIRA_SNAME,
677 shorthostname, 1, KEYFILE);
678 if (status)
679 status += ERROR_TABLE_BASE_krb;
680 else
681 status = mr_auth("reg_svr");
682 if (status)
683 {
684 com_err(whoami, status, "authenticating to moira");
685 mr_disconnect();
686 return MR_INTERNAL;
687 }
688
689 sprintf(uidbuf, "%d", uid);
690 qargv[0] = uidbuf;
691 qargv[1] = username;
4787f97b 692 qargv[2] = "IMAP";
b50f996d 693 status = mr_query("register_user", 3, qargv, NULL, NULL);
694 mr_disconnect();
695 return status;
696}
697
698
699/* Find some typical available usernames */
700
701char *uname_patterns[] = {
702 "FL", /* johndoe */
703 "fmllllll", /* jmdoe... (last name truncated) */
704 "flllllll", /* jdoe.... ("") */
705 "llllllll", /* doe..... ("") */
706 "fml", /* jmd */
707 "Fl", /* johnd */
708 "Lf", /* doej */
709 "Lfm", /* doejm */
710 "F", /* john */
711};
712int num_patterns = sizeof(uname_patterns) / sizeof(char *);
713
714char *find_usernames(char *first, char *middle, char *last)
715{
716 EXEC SQL BEGIN DECLARE SECTION;
717 char username[2 * USERS_LOGIN_SIZE];
718 int count;
719 EXEC SQL END DECLARE SECTION;
720 int pat, len;
721 char *pp, *up, *fp, *mp, *lp, *unames = NULL;
722
723 fixname(first);
724 fixname(middle);
725 fixname(last);
726
727 for (pat = 0; pat < num_patterns; pat++)
728 {
729 up = username;
730 fp = first;
731 mp = middle;
732 lp = last;
733 for (pp = uname_patterns[pat]; *pp; pp++)
734 {
735 switch (*pp)
736 {
737 case 'f':
738 if (*fp)
739 *up++ = *fp++;
740 break;
741
742 case 'F':
743 if (up - username + strlen(first) < USERS_LOGIN_SIZE)
744 up += sprintf(up, "%s", first);
745 else
746 goto nextpattern;
747 break;
748
749 case 'm':
750 if (!*middle)
751 goto nextpattern;
752 if (*mp)
753 *up++ = *mp++;
754 break;
755
756 case 'l':
757 if (*lp)
758 *up++ = *lp++;
759 break;
760
761 case 'L':
762 if (up - username + strlen(last) < USERS_LOGIN_SIZE)
763 up += sprintf(up, "%s", last);
764 else
765 goto nextpattern;
766 break;
767 }
768 }
769 *up = '\0';
770
d1d04a6c 771 if (strlen(username) < 3 || strlen(username) >= USERS_LOGIN_SIZE)
b50f996d 772 continue;
773
774 EXEC SQL SELECT COUNT(login) INTO :count FROM users
775 WHERE login = :username;
776 if (sqlca.sqlcode)
8dc13a24 777 {
778 errno = MR_DBMS_ERR;
779 return NULL;
780 }
b50f996d 781 if (count == 0)
782 {
783 EXEC SQL SELECT COUNT(name) INTO :count FROM list
784 WHERE name = :username;
785 if (sqlca.sqlcode)
8dc13a24 786 {
787 errno = MR_DBMS_ERR;
788 return NULL;
789 }
b50f996d 790 }
791 if (count == 0)
792 {
793 EXEC SQL SELECT COUNT(label) INTO :count FROM filesys
794 WHERE label = :username;
795 if (sqlca.sqlcode)
8dc13a24 796 {
797 errno = MR_DBMS_ERR;
798 return NULL;
799 }
b50f996d 800 }
801
802 if (count == 0)
803 {
804 if (unames)
805 {
806 unames = realloc(unames, strlen(unames) + strlen(username) + 3);
807 if (!unames)
808 return NULL;
809 strcat(unames, ", ");
810 strcat(unames, username);
811 }
812 else
813 {
814 unames = strdup(username);
815 if (!unames)
816 return NULL;
817 }
818 }
819
820 nextpattern:
821 ;
822 }
823
8dc13a24 824 /* unames will be NULL if we couldn't suggest a username. Clear
825 errno so the caller can distinguish this from an error case. */
826 errno = 0;
b50f996d 827 return unames;
828}
829
830void fixname(char *name)
831{
832 char *s, *d;
833
834 for (s = d = name; *s; s++)
835 {
836 if (isalnum(*s))
837 *d++ = tolower(*s);
838 }
839 *d = '\0';
840}
841
842void *xmalloc(size_t bytes)
843{
844 void *buf = malloc(bytes);
845
846 if (buf)
847 return buf;
848
849 com_err(whoami, errno, "in xmalloc");
850 exit(1);
851}
852
853void *xrealloc(void *ptr, size_t bytes)
854{
855 void *buf = realloc(ptr, bytes);
856
857 if (buf)
858 return buf;
859
860 com_err(whoami, errno, "in xrealloc");
861 exit(1);
862}
863
864char *xstrdup(char *str)
865{
866 char *buf = strdup(str);
867
868 if (buf)
869 return buf;
870
871 com_err(whoami, errno, "in xstrdup");
872 exit(1);
873}
874
875void mr_com_err(const char *whoami, long code, const char *fmt, va_list pvar)
876{
877 if (whoami)
878 {
879 fputs(whoami, stderr);
880 if (cl)
881 fprintf(stderr, "[#%d]", cl->clientid);
882 fputs(": ", stderr);
883 }
884 if (code) {
885 fputs(error_message(code), stderr);
886 fputs(" ", stderr);
887 }
888 if (fmt)
889 vfprintf(stderr, fmt, pvar);
890 putc('\n', stderr);
891}
892
893void sigshut(int sig)
894{
895 state = RS_EXITING;
896}
This page took 0.176888 seconds and 5 git commands to generate.