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