source: trunk/third/moira/regtape/common.pc @ 26024

Revision 26024, 13.9 KB checked in by jdreed, 11 years ago (diff)
In moira: * Snapshot moira at r4113 to pick up new firewall-related changes
Line 
1/* $Id: common.pc 4111 2013-05-22 20:26:51Z zacheiss $
2 *
3 * Staff/Student load common code
4 *
5 * Copyright (C) 1999 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 <moira_site.h>
13#include <moira_schema.h>
14#include "common.h"
15
16#include <ctype.h>
17#include <string.h>
18#include <stdio.h>
19
20EXEC SQL INCLUDE sqlca;
21extern void sqlglm(char *, unsigned int *, unsigned int *);
22
23RCSID("$HeadURL: svn+ssh://svn.mit.edu/moira/trunk/moira/regtape/common.pc $ $Id: common.pc 4111 2013-05-22 20:26:51Z zacheiss $");
24
25EXEC SQL BEGIN DECLARE SECTION;
26extern char *prog;
27extern int who;
28EXEC SQL END DECLARE SECTION;
29
30extern char *whoami;
31
32#define MIN_ID_VALUE 100
33#define MAX_ID_VALUE 131072
34
35/* Remove non-digits from a phone number. */
36void fixphone(char *phone)
37{
38  char *d = phone;
39
40  while (*phone)
41    {
42      if (isdigit(*phone))
43        *d++ = *phone;
44      phone++;
45    }
46  *d = '\0';
47}
48
49/* Remove characters from address that aren't safe for passwd files. */
50void fixaddress(char *address)
51{
52  char *p;
53
54  while ((p = strchr(address, ',')))
55    *p = ';';
56  while ((p = strchr(address, ':')))
57    *p = ';';
58
59
60void process_entry(struct entry *e, int secure)
61{
62  int changed;
63  char buf[MAX_FIELD_WIDTH], *from, *to;
64  EXEC SQL BEGIN DECLARE SECTION;
65  char *first, *last, *middle, *sid;
66  char *name = e->name, *xtitle = e->xtitle, *xaddr = e->xaddress;
67  char *xphone1 = e->xphone1, *xphone2 = e->xphone2;
68  char type[USERS_TYPE_SIZE], oaddr[USERS_OFFICE_ADDR_SIZE];
69  char ophone[USERS_OFFICE_PHONE_SIZE], dept[USERS_DEPARTMENT_SIZE];
70  char haddr[USERS_HOME_ADDR_SIZE], hphone[USERS_HOME_PHONE_SIZE];
71  char dfirst[USERS_FIRST_SIZE], dlast[USERS_LAST_SIZE];
72  char dmiddle[USERS_MIDDLE_SIZE];
73  char affiliation_basic[USERS_AFFILIATION_BASIC_SIZE];
74  char affiliation_detailed[USERS_AFFILIATION_DETAILED_SIZE];
75  char mit_email[USERS_LOGIN_SIZE + 9]; /* strlen("@mit.edu") + 1; */
76  char alternate_email[USERS_ALTERNATE_EMAIL_SIZE];
77  int id, status, fmodby, xnlen = USERS_XNAME_SIZE - 1;
78  EXEC SQL END DECLARE SECTION;
79
80  sid = e->id;
81  last = e->last;
82  if (strlen(last) > USERS_LAST_SIZE - 1)
83    last[USERS_LAST_SIZE - 1] = '\0';
84  first = e->first;
85  if (strlen(first) > USERS_FIRST_SIZE - 1)
86    first[USERS_FIRST_SIZE - 1] = '\0';
87  middle = e->middle;
88  if (strlen(middle) > USERS_MIDDLE_SIZE - 1)
89    middle[USERS_MIDDLE_SIZE - 1] = '\0';
90  id = 0;
91
92  /* Get user info */
93  EXEC SQL SELECT users_id, login||'@mit.edu', first, last, middle, type, office_addr,
94    office_phone, home_addr, home_phone, department, status, fmodby,
95    affiliation_basic, affiliation_detailed, alternate_email
96    INTO :id, :mit_email, :dfirst, :dlast, :dmiddle, :type, :oaddr,
97    :ophone, :haddr, :hphone, :dept, :status, :fmodby,
98    :affiliation_basic, :affiliation_detailed, :alternate_email
99    FROM users
100    WHERE clearid = :sid AND status != 3;
101  if (sqlfail())
102    {
103      if (sqlca.sqlcode == SQL_DUPLICATE)
104        {
105          com_err(whoami, 0, "duplicate ID number %s on user %s %s",
106                  sid, first, last);
107          return;
108        }
109      else
110        sqlexit();
111    }
112  if (id == 0)
113    {
114      newuser(e, secure);
115      return;
116    }
117  strtrim(dfirst);
118  strtrim(dlast);
119  strtrim(dmiddle);
120  strtrim(type);
121
122  /* Update type/state if necessary.  (Exclude several spacial cases.) */
123  if (strcmp(e->type, type) &&
124      strcmp(type, "STAFF") && strcmp(type, "SIPBMEM") &&
125      strcmp(type, "KNIGHT"))
126    {
127      com_err(whoami, 0, "updating type for %s %s from \"%s\" to \"%s\"",
128              first, last, type, e->type);
129      if (status == US_NOT_ALLOWED)
130        status = US_NO_LOGIN_YET;
131      else if (status == US_ENROLL_NOT_ALLOWED)
132        status = US_ENROLLED;
133      strcpy(type, e->type);
134      EXEC SQL UPDATE users
135        SET type = NVL(:type, CHR(0)), status = :status,
136        modtime = SYSDATE, modby = :who, modwith = :prog
137        WHERE users_id = :id;
138      if (sqlca.sqlcode)
139        {
140          dbmserr("updating user", sqlca.sqlcode);
141          exit(1);
142        }
143    }
144
145  /* Update name if necessary */
146  if (strcmp(first, dfirst) || strcmp(last, dlast) || strcmp(middle, dmiddle))
147    {
148      com_err(whoami, 0, "updating real name for %s%s%s %s (was %s%s%s %s)",
149              first, *middle ? " " : "", middle, last,
150              dfirst, *dmiddle ? " " : "", dmiddle, dlast);
151      EXEC SQL UPDATE users
152        SET first = NVL(:first, CHR(0)), last = NVL(:last, CHR(0)),
153        middle = NVL(:middle, CHR(0)), modby = :who, modwith = :prog,
154        modtime = SYSDATE
155        WHERE users_id = :id;
156      if (sqlca.sqlcode)
157        {
158          dbmserr("updating name", sqlca.sqlcode);
159          exit(1);
160        }
161    }
162
163  /* Update affiliation information */
164  strtrim(affiliation_basic);
165  strtrim(affiliation_detailed);
166  if (strcmp(affiliation_basic, e->affiliation_basic) ||
167      strcmp(affiliation_detailed, e->affiliation_detailed))
168    {
169      com_err(whoami, 0, "affiliation for %s %s changed from \"%s (%s)\" to \"%s (%s)\"",
170              first, last, affiliation_detailed, affiliation_basic, e->affiliation_detailed,
171              e->affiliation_basic);
172
173      strlcpy(affiliation_basic, e->affiliation_basic, USERS_AFFILIATION_BASIC_SIZE);
174      strlcpy(affiliation_detailed, e->affiliation_detailed, USERS_AFFILIATION_DETAILED_SIZE);
175
176      EXEC SQL UPDATE users
177        SET affiliation_basic = NVL(:affiliation_basic, CHR(0)),
178        affiliation_detailed = NVL(:affiliation_detailed, CHR(0)),
179        modby = :who, modwith = :prog, modtime = SYSDATE
180        WHERE users_id = :id;
181      if (sqlca.sqlcode)
182        {
183          dbmserr("updating affiliation", sqlca.sqlcode);
184          exit(1);
185        }
186    }
187
188  /* Update alternate email information, if any */
189  strtrim(alternate_email);
190  strtrim(mit_email);
191  if (strlen(e->email_address) > 0)
192    {
193      /* If directory information email address is the default, treat is as empty. */
194      if (!strcmp(mit_email, e->email_address))
195        e->email_address = "";
196
197      if (strcmp(alternate_email, e->email_address))
198        {
199          com_err(whoami, 0, "alternate email for %s %s changed from \"%s\" to \"%s\"",
200                  first, last, alternate_email, e->email_address);
201         
202          strlcpy(alternate_email, e->email_address, USERS_ALTERNATE_EMAIL_SIZE);
203         
204          EXEC SQL UPDATE users SET alternate_email = NVL(:alternate_email, CHR(0)),
205            modby = :who, modwith = :prog, modtime = SYSDATE
206            WHERE users_id = :id;
207          if (sqlca.sqlcode)
208            {
209              dbmserr("updating alternate email", sqlca.sqlcode);
210              exit(1);
211            }
212        }
213    }
214
215  /* Update finger info fields if they have changed and the user
216   * didn't set them blank.
217   */
218  changed = 0;
219
220  if (strncmp(strtrim(oaddr), e->oaddr, USERS_OFFICE_ADDR_SIZE - 1) &&
221      (*oaddr || fmodby != id))
222    {
223      changed++;
224      com_err(whoami, 0, "office for %s %s changed from \"%s\" to \"%s\"",
225              first, last, oaddr, e->oaddr);
226      strlcpy(oaddr, e->oaddr, USERS_OFFICE_ADDR_SIZE);
227    }
228
229  if (strncmp(strtrim(ophone), e->ophone, USERS_OFFICE_PHONE_SIZE - 1) &&
230      (*ophone || fmodby != id))
231    {
232      changed++;
233      com_err(whoami, 0, "Phone for %s %s changed from \"%s\" to \"%s\"",
234              first, last, ophone, e->ophone);
235      strlcpy(ophone, e->ophone, USERS_OFFICE_PHONE_SIZE);
236    }
237
238  if (strncmp(strtrim(haddr), e->haddr, USERS_HOME_ADDR_SIZE - 1) &&
239      (*haddr || fmodby != id))
240    {
241      changed++;
242      com_err(whoami, 0, "home addr for %s %s changed from \"%s\" to \"%s\"",
243              first, last, haddr, e->haddr);
244      strlcpy(haddr, e->haddr, USERS_HOME_ADDR_SIZE);
245    }
246
247  if (strncmp(strtrim(hphone), e->hphone, USERS_HOME_PHONE_SIZE - 1) &&
248      (*hphone || fmodby != id))
249    {
250      changed++;
251      com_err(whoami, 0, "Phone for %s %s changed from \"%s\" to \"%s\"",
252              first, last, hphone, e->hphone);
253      strlcpy(hphone, e->hphone, USERS_HOME_PHONE_SIZE);
254    }
255
256  if (strncmp(strtrim(dept), e->dept, USERS_DEPARTMENT_SIZE - 1) &&
257      (*dept || fmodby != id))
258    {
259      changed++;
260      com_err(whoami, 0, "Department for %s %s changed from \"%s\" to \"%s\"",
261              first, last, dept, e->dept);
262      strlcpy(dept, e->dept, USERS_DEPARTMENT_SIZE);
263    }
264
265  if (changed)
266    {
267      com_err(whoami, 0, "updating finger for %s %s", first, last);
268      EXEC SQL UPDATE users
269        SET office_addr = NVL(:oaddr, CHR(0)),
270        office_phone = NVL(:ophone, CHR(0)), home_addr = NVL(:haddr, CHR(0)),
271        home_phone = NVL(:hphone, CHR(0)), department = NVL(:dept, CHR(0)),
272        fmodtime = SYSDATE, fmodby = :who, fmodwith = :prog,
273        xname = NVL(SUBSTR(:name, 0, :xnlen), CHR(0)),
274        xdept = NVL(:dept, CHR(0)), xtitle = NVL(:xtitle, CHR(0)),
275        xaddress = NVL(:xaddr, CHR(0)), xphone1 = NVL(:xphone1, CHR(0)),
276        xphone2 = NVL(:xphone2, CHR(0)), xmodtime = SYSDATE
277        WHERE users_id = :id;
278      if (sqlca.sqlcode)
279        {
280          dbmserr(NULL, sqlca.sqlcode);
281          exit(1);
282        }
283    }
284  else
285    {
286      EXEC SQL UPDATE users
287        SET xname = NVL(SUBSTR(:name, 0, :xnlen), CHR(0)),
288        xdept = NVL(:dept, CHR(0)), xtitle = NVL(:xtitle, CHR(0)),
289        xaddress = NVL(:xaddr, CHR(0)), xphone1 = NVL(:xphone1, CHR(0)),
290        xphone2 = NVL(:xphone2, CHR(0)), xmodtime = SYSDATE
291        WHERE users_id = :id;
292      if (sqlca.sqlcode)
293        {
294          dbmserr(NULL, sqlca.sqlcode);
295          exit(1);
296        }
297    }
298}
299
300void newuser(struct entry *e, int secure)
301{
302  EXEC SQL BEGIN DECLARE SECTION;
303  int issecure = secure, users_id, uid, st, xnlen = USERS_XNAME_SIZE - 1;
304  int oadlen = USERS_OFFICE_ADDR_SIZE - 1;
305  int ophlen = USERS_OFFICE_PHONE_SIZE - 1;
306  char login[USERS_LOGIN_SIZE];
307  char *id, *last, *first, *middle, *type;
308  char *name, *dept, *haddr, *hphone, *oaddr, *ophone;
309  char *xtitle, *xaddress, *xphone1, *xphone2;
310  char *affiliation_basic, *affiliation_detailed;
311  EXEC SQL END DECLARE SECTION;
312
313  users_id = set_next_users_id();
314  uid = set_next_uid();
315  sprintf(login, "#%d", uid);
316  if (!strcmp(e->type, "LINCOLN"))
317    st = US_NO_LOGIN_YET_KERBEROS_ONLY;
318  else
319    st = US_NO_LOGIN_YET;
320  last = e->last;
321  first = e->first;
322  middle = e->middle;
323  id = e->id;
324  type = e->type;
325  name = e->name;
326  dept = e->dept;
327  haddr = e->haddr;
328  hphone = e->hphone;
329  oaddr = e->oaddr;
330  ophone = e->ophone;
331  xtitle = e->xtitle;
332  xaddress = e->xaddress;
333  xphone1 = e->xphone1;
334  xphone2 = e->xphone2;
335  affiliation_basic = e->affiliation_basic;
336  affiliation_detailed = e->affiliation_detailed;
337 
338  com_err(whoami, 0, "adding user %s %s", e->first, e->last);
339
340  EXEC SQL INSERT INTO users
341    (login, users_id, unix_uid, shell, winconsoleshell, last, first,
342     middle, status, clearid, type, modtime, modby, modwith, fullname,
343     department, home_addr, home_phone, office_addr, office_phone, fmodtime,
344     fmodby, fmodwith, potype, pmodtime, pmodby, pmodwith,
345     xname, xdept, xtitle, xaddress, xphone1, xphone2, xmodtime, secure,
346     created, creator, winhomedir, winprofiledir, sponsor_type,
347     sponsor_id, expiration, affiliation_basic, affiliation_detailed)
348    VALUES (:login, :users_id, :uid, '/bin/athena/bash', 'cmd',
349            NVL(:last, CHR(0)), NVL(:first, CHR(0)), NVL(:middle, CHR(0)),
350            :st, NVL(:id, CHR(0)), NVL(:type, CHR(0)), SYSDATE, :who, :prog,
351            NVL(:name, CHR(0)), NVL(:dept, CHR(0)), NVL(:haddr, CHR(0)),
352            NVL(:hphone, CHR(0)), NVL(SUBSTR(:oaddr, 0, :oadlen), CHR(0)),
353            NVL(SUBSTR(:ophone, 0, :ophlen), CHR(0)), SYSDATE, :who, :prog,
354            'NONE', SYSDATE, :who, :prog,
355            NVL(SUBSTR(:name, 0, :xnlen), CHR(0)), NVL(:dept, CHR(0)),
356            NVL(:xtitle, CHR(0)), NVL(:xaddress, CHR(0)),
357            NVL(:xphone1, CHR(0)), NVL(:xphone2, CHR(0)), SYSDATE, :issecure,
358            SYSDATE, :who, '[DFS]', '[DFS]', 'NONE', 0, CHR(0), :affiliation_basic,
359            :affiliation_detailed);
360  if (sqlca.sqlcode)
361    {
362      dbmserr("adding user", sqlca.sqlcode);
363      exit(1);
364    }
365}
366
367int set_next_users_id(void)
368{
369  EXEC SQL BEGIN DECLARE SECTION;
370  int flag, value, retval;
371  EXEC SQL END DECLARE SECTION;
372
373  EXEC SQL SELECT value INTO :value FROM numvalues
374    WHERE name = 'users_id';
375  if (sqlfail())
376    sqlexit();
377  if (sqlca.sqlerrd[2] != 1)
378    {
379      EXEC SQL ROLLBACK;
380      com_err(whoami, MR_INTERNAL, "values table inconsistancy");
381      exit(1);
382    }
383
384  flag = 0;
385  EXEC SQL SELECT users_id INTO :flag FROM users
386    WHERE users_id = :value;
387  if (sqlfail())
388    sqlexit();
389  if (sqlca.sqlerrd[2] == 0)
390    flag = 0;
391  while (flag)
392    {
393      value++;
394      flag = 0;
395      EXEC SQL SELECT users_id INTO :flag FROM users
396        WHERE users_id = :value;
397      if (sqlfail())
398        sqlexit();
399      if (sqlca.sqlerrd[2] == 0)
400        flag = 0;
401    }
402
403  retval = value++;
404  EXEC SQL UPDATE numvalues SET value = :value
405    WHERE name = 'users_id';
406  if (sqlca.sqlcode)
407    {
408      dbmserr("assigning ID", sqlca.sqlcode);
409      exit(1);
410    }
411  return retval;
412}
413
414int set_next_uid(void)
415{
416  EXEC SQL BEGIN DECLARE SECTION;
417  int flag, initial, value, retval;
418  EXEC SQL END DECLARE SECTION;
419
420  EXEC SQL SELECT value INTO :initial FROM numvalues
421    WHERE name = 'unix_uid';
422  if (sqlfail())
423    sqlexit();
424  if (sqlca.sqlerrd[2] != 1)
425    {
426      EXEC SQL ROLLBACK;
427      com_err(whoami, MR_INTERNAL, "values table inconsistancy");
428      exit(1);
429    }
430
431  value = initial;
432  flag = 0;
433  EXEC SQL SELECT COUNT(unix_uid) INTO :flag
434    FROM users WHERE unix_uid = :value;
435  if (sqlfail())
436    sqlexit();
437  if (sqlca.sqlerrd[2] == 0)
438    flag = 0;
439  while (flag)
440    {
441      value++;
442#ifdef ULTRIX_ID_HOLE
443      if (value > 31999 && value < 32768)
444        value = 32768;
445#endif
446      if (value > MAX_ID_VALUE)
447        value = MIN_ID_VALUE;
448      if (value == initial)
449        {
450          com_err(whoami, 0, "Out of uids!");
451          EXEC SQL ROLLBACK WORK;
452          exit(1);
453        }
454      flag = 0;
455      EXEC SQL SELECT COUNT(unix_uid) INTO :flag
456        FROM users WHERE unix_uid = :value;
457      if (sqlfail())
458        sqlexit();
459    }
460
461  retval = value++;
462  if (value > MAX_ID_VALUE)
463    value = MIN_ID_VALUE;
464  EXEC SQL UPDATE numvalues SET value = :value WHERE name = 'unix_uid';
465  if (sqlca.sqlcode)
466    {
467      dbmserr("assigning ID", sqlca.sqlcode);
468      exit(1);
469    }
470  return retval;
471}
472
473void sqlexit(void)
474{
475  dbmserr(NULL, sqlca.sqlcode);
476  EXEC SQL ROLLBACK WORK;
477  exit(1);
478}
479
480void dbmserr(char *where, int what)
481{
482  char err_msg[256];
483  int bufsize = 256, msglength = 0;
484
485  sqlglm(err_msg, &bufsize, &msglength);
486  err_msg[msglength] = '\0';
487
488  if (where)
489    com_err(whoami, 0, "DBMS error %swhile %s", err_msg, where);
490  else
491    com_err(whoami, 0, "DBMS error %s", err_msg);
492}
Note: See TracBrowser for help on using the repository browser.