]> andersk Git - moira.git/blob - server/qsetup.pc
Check the length of a new user's full name against USERS_FULLNAME_SIZE
[moira.git] / server / qsetup.pc
1 /* $Id$
2  *
3  * Query setup routines
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 "mr_server.h"
12 #include "query.h"
13 #include "qrtn.h"
14
15 #include <arpa/inet.h>
16 #include <netinet/in.h>
17
18 #include <ctype.h>
19 #include <stdlib.h>
20 #include <string.h>
21
22 EXEC SQL INCLUDE sqlca;
23
24 RCSID("$Header$");
25
26 extern char *whoami;
27 extern int dbms_errno, mr_errcode;
28
29 EXEC SQL BEGIN DECLARE SECTION;
30 extern char stmt_buf[];
31 EXEC SQL END DECLARE SECTION;
32
33 EXEC SQL WHENEVER SQLERROR DO dbmserr();
34
35
36 int prefetch_value(struct query *q, char **argv, client *cl);
37 int check_nfs(int mach_idx, char *name, char *access);
38
39 /* Setup Routines */
40
41 /* Setup routine for add_user
42  *
43  * Inputs: argv[0] - login
44  *         argv[1] - uid
45  *
46  * Description:
47  *
48  * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid)
49  * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>"
50  */
51
52 int setup_ausr(struct query *q, char *argv[], client *cl)
53 {
54   int row, err;
55   EXEC SQL BEGIN DECLARE SECTION;
56   int nuid;
57   EXEC SQL END DECLARE SECTION;
58
59   if (!strcmp(q->shortname, "uusr") || !strcmp(q->shortname, "uuac"))
60     row = 2;
61   else
62     row = 1;
63
64   if (strlen(argv[row + 2]) + strlen(argv[row + 3]) +
65       strlen(argv[row + 4]) + 2 > USERS_FULLNAME_SIZE)
66     return MR_ARG_TOO_LONG;
67
68   if (!strcmp(argv[row], UNIQUE_UID) || atoi(argv[row]) == -1)
69     {
70       if ((err = set_next_object_id("unix_uid", USERS_TABLE, 1)))
71         return err;
72       EXEC SQL SELECT value INTO :nuid FROM numvalues WHERE name = 'unix_uid';
73       if (sqlca.sqlerrd[2] != 1)
74         return MR_INTERNAL;
75       sprintf(argv[row], "%d", nuid);
76     }
77
78   if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[row]) == -1)
79     sprintf(argv[0], "#%s", argv[row]);
80
81   if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
82     return mr_errcode;
83
84   return MR_SUCCESS;
85 }
86
87
88 /* setup_dusr - verify that the user is no longer being referenced
89  * and may safely be deleted.
90  */
91
92 int setup_dusr(struct query *q, char *argv[], client *cl)
93 {
94   EXEC SQL BEGIN DECLARE SECTION;
95   int flag, id, cnt;
96   EXEC SQL END DECLARE SECTION;
97
98   id = *(int *)argv[0];
99
100   /* For now, only allow users to be deleted if their status is 0 */
101   EXEC SQL SELECT status INTO :flag FROM users WHERE users_id = :id;
102   if (flag != 0 && flag != 4)
103     return MR_IN_USE;
104
105   EXEC SQL DELETE FROM quota WHERE entity_id = :id AND type = 'USER';
106   EXEC SQL DELETE FROM krbmap WHERE users_id = :id;
107   EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
108     WHERE member_id = :id AND member_type = 'USER';
109   if (cnt > 0)
110     return MR_IN_USE;
111   EXEC SQL SELECT COUNT(label) INTO :cnt FROM filesys
112     WHERE owner = :id;
113   if (cnt > 0)
114     return MR_IN_USE;
115   EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
116     WHERE acl_id = :id AND acl_type = 'USER';
117   if (cnt > 0)
118     return MR_IN_USE;
119   EXEC SQL SELECT COUNT(name) INTO :cnt FROM servers
120     WHERE acl_id = :id AND acl_type = 'USER';
121   if (cnt > 0)
122     return MR_IN_USE;
123   EXEC SQL SELECT COUNT(acl_id) INTO :cnt FROM hostaccess
124     WHERE acl_id = :id AND acl_type = 'USER';
125   if (cnt > 0)
126     return MR_IN_USE;
127   if (dbms_errno)
128     return mr_errcode;
129   return MR_SUCCESS;
130 }
131
132
133 /* setup_spop: verify that there is already a valid POP machine_id in the
134  * pop_id field.  Also take care of keeping track of the post office usage.
135  */
136 int setup_spop(struct query *q, char *argv[], client *cl)
137 {
138   EXEC SQL BEGIN DECLARE SECTION;
139   int id, mid;
140   char type[USERS_POTYPE_SIZE];
141   EXEC SQL END DECLARE SECTION;
142
143   id = *(int *)argv[0];
144   EXEC SQL SELECT potype, pop_id INTO :type, :mid FROM users
145     WHERE users_id = :id;
146   if (sqlca.sqlerrd[2] == 0)
147     return MR_MACHINE;
148   EXEC SQL SELECT mach_id INTO :mid FROM machine
149     WHERE mach_id = :mid;
150   if (sqlca.sqlerrd[2] == 0)
151     return MR_MACHINE;
152   if (strcmp(strtrim(type), "POP"))
153     set_pop_usage(mid, 1);
154   return MR_SUCCESS;
155 }
156
157
158 /* setup_dpob:  Take care of keeping track of the post office usage.
159  */
160 int setup_dpob(struct query *q, char *argv[], client *cl)
161 {
162   EXEC SQL BEGIN DECLARE SECTION;
163   int id, user;
164   char type[USERS_POTYPE_SIZE];
165   EXEC SQL END DECLARE SECTION;
166
167   user = *(int *)argv[0];
168   EXEC SQL SELECT potype, pop_id INTO :type, :id FROM users
169     WHERE users_id = :user;
170   if (dbms_errno)
171     return mr_errcode;
172
173   if (!strcmp(strtrim(type), "POP"))
174     set_pop_usage(id, -1);
175   return MR_SUCCESS;
176 }
177
178
179 /* setup_dmac - verify that the machine is no longer being referenced
180  * and may safely be deleted.
181  */
182
183 int setup_dmac(struct query *q, char *argv[], client *cl)
184 {
185   EXEC SQL BEGIN DECLARE SECTION;
186   int flag, id, cnt;
187   EXEC SQL END DECLARE SECTION;
188
189   id = *(int *)argv[0];
190
191   EXEC SQL SELECT status INTO :flag FROM machine
192     WHERE mach_id = :id;
193   if (flag != 3)
194     return MR_IN_USE;
195   EXEC SQL SELECT COUNT(login) INTO :cnt FROM users
196     WHERE potype = 'POP' AND pop_id = :id;
197   if (cnt > 0)
198     return MR_IN_USE;
199   EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM serverhosts
200     WHERE mach_id = :id;
201   if (cnt > 0)
202     return MR_IN_USE;
203   EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM nfsphys
204     WHERE mach_id = :id;
205   if (cnt > 0)
206     return MR_IN_USE;
207   EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM hostaccess
208     WHERE mach_id = :id;
209   if (cnt > 0)
210     return MR_IN_USE;
211   EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM printcap
212     WHERE mach_id = :id;
213   if (cnt > 0)
214     return MR_IN_USE;
215   EXEC SQL SELECT COUNT(quotaserver) INTO :cnt FROM printcap
216     WHERE quotaserver = :id;
217   if (cnt > 0)
218     return MR_IN_USE;
219   EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM palladium
220     WHERE mach_id = :id;
221   if (cnt > 0)
222     return MR_IN_USE;
223   EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM hostalias
224     WHERE mach_id = :id;
225   if (cnt > 0)
226     return MR_IN_USE;
227
228   EXEC SQL DELETE FROM mcmap WHERE mach_id = :id;
229   if (dbms_errno)
230     return mr_errcode;
231   return MR_SUCCESS;
232 }
233
234
235 /* setup_dsnt - verify that the subnet is no longer being referenced
236  * and may safely be deleted.
237  */
238
239 int setup_dsnt(struct query *q, char *argv[], client *cl)
240 {
241   EXEC SQL BEGIN DECLARE SECTION;
242   int id, cnt = 0;
243   EXEC SQL END DECLARE SECTION;
244
245   id = *(int *)argv[0];
246   EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM machine
247     WHERE snet_id = :id;
248   if (cnt > 0)
249     return MR_IN_USE;
250   return MR_SUCCESS;
251 }
252
253
254 /* setup_dclu - verify that the cluster is no longer being referenced
255  * and may safely be deleted.
256  */
257
258 int setup_dclu(struct query *q, char *argv[], client *cl)
259 {
260   EXEC SQL BEGIN DECLARE SECTION;
261   int id, cnt;
262   EXEC SQL END DECLARE SECTION;
263
264   id = *(int *)argv[0];
265   EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM mcmap
266     WHERE clu_id = :id;
267   if (cnt > 0)
268     return MR_IN_USE;
269   EXEC SQL SELECT COUNT(clu_id) INTO :cnt FROM svc
270     WHERE clu_id = :id;
271   if (cnt > 0)
272     return MR_IN_USE;
273   if (dbms_errno)
274     return mr_errcode;
275   return MR_SUCCESS;
276 }
277
278
279 /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
280  * a new gid and put it in argv[6].  Otherwise if argv[6] is UNIQUE_ID but
281  * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
282  * a -1 there.  Remember that this is also used for ulis, with the indexes
283  * at 6 & 7.  Also check that the list name does not contain uppercase
284  * characters, control characters, @, or :.
285  */
286
287 static int badlistchars[] = {
288   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
289   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
290   1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
291   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* 0 - ? */
292   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
293   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, /* P - _ */
294   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
295   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
296   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
297   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
298   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
299   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
300   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
301   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
302   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
303   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
304 };
305
306 int setup_alis(struct query *q, char *argv[], client *cl)
307 {
308   EXEC SQL BEGIN DECLARE SECTION;
309   int ngid;
310   EXEC SQL END DECLARE SECTION;
311   unsigned char *p;
312   int idx, err;
313
314   if (!strcmp(q->shortname, "alis"))
315     idx = 0;
316   else if (!strcmp(q->shortname, "ulis"))
317     idx = 1;
318
319   if (idx == 1)
320     {
321       EXEC SQL BEGIN DECLARE SECTION;
322       int lid = *(int *)argv[0];
323       EXEC SQL END DECLARE SECTION;
324
325       if (acl_access_check(lid, cl))
326         return MR_PERM;
327     }
328
329   for (p = (unsigned char *) argv[idx]; *p; p++)
330     {
331       if (badlistchars[*p])
332         return MR_BAD_CHAR;
333     }
334
335   if (!strcmp(argv[6 + idx], UNIQUE_GID) || atoi(argv[6 + idx]) == -1)
336     {
337       if (atoi(argv[5 + idx]))
338         {
339           if ((err = set_next_object_id("gid", LIST_TABLE, 1)))
340             return err;
341           EXEC SQL SELECT value INTO :ngid FROM numvalues
342             WHERE name = 'gid';
343           if (dbms_errno)
344             return mr_errcode;
345           sprintf(argv[6 + idx], "%d", ngid);
346         }
347       else
348         strcpy(argv[6 + idx], "-1");
349     }
350
351   if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
352     return mr_errcode;
353
354   return MR_SUCCESS;
355 }
356
357
358 /* setup_dlis - verify that the list is no longer being referenced
359  * and may safely be deleted.
360  */
361
362 int setup_dlis(struct query *q, char *argv[], client *cl)
363 {
364   int id;
365   EXEC SQL BEGIN DECLARE SECTION;
366   int cnt;
367   EXEC SQL END DECLARE SECTION;
368
369   id = *(int *)argv[0];
370
371   EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
372     WHERE member_id = :id AND member_type = 'LIST';
373   if (cnt > 0)
374     return MR_IN_USE;
375
376   EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
377     WHERE member_id = :id AND member_type = 'LIST';
378   if (cnt > 0)
379     return MR_IN_USE;
380
381   EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
382     WHERE list_id = :id;
383   if (cnt > 0)
384     return MR_IN_USE;
385
386   EXEC SQL SELECT COUNT(label) INTO :cnt FROM filesys WHERE owners = :id;
387   if (cnt > 0)
388     return MR_IN_USE;
389
390   EXEC SQL SELECT COUNT(tag) INTO :cnt FROM capacls WHERE list_id = :id;
391   if (cnt > 0)
392     return MR_IN_USE;
393
394   EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
395     WHERE acl_id = :id AND acl_type = 'LIST' AND list_id != :id;
396   if (cnt > 0)
397     return MR_IN_USE;
398
399   EXEC SQL SELECT COUNT(name) INTO :cnt FROM servers
400     WHERE acl_id = :id AND acl_type = 'LIST';
401   if (cnt > 0)
402     return MR_IN_USE;
403
404   EXEC SQL SELECT COUNT(entity_id) INTO :cnt FROM quota
405     WHERE entity_id = :id AND type = 'GROUP';
406   if (cnt > 0)
407     return MR_IN_USE;
408
409   EXEC SQL SELECT COUNT(acl_id) INTO :cnt FROM hostaccess
410     WHERE acl_id = :id AND acl_type = 'LIST';
411   if (cnt > 0)
412     return MR_IN_USE;
413
414   EXEC SQL SELECT COUNT(class) INTO :cnt FROM zephyr z
415     WHERE z.xmt_type = 'LIST' AND z.xmt_id = :id
416     OR z.sub_type = 'LIST' AND z.sub_id = :id
417     OR z.iws_type = 'LIST' AND z.iws_id = :id
418     OR z.iui_type = 'LIST' AND z.iui_id = :id;
419   if (cnt > 0)
420     return MR_IN_USE;
421
422   return MR_SUCCESS;
423 }
424
425
426 /* setup_dsin - verify that the service is no longer being referenced
427  * and may safely be deleted.
428  */
429
430 int setup_dsin(struct query *q, char *argv[], client *cl)
431 {
432   EXEC SQL BEGIN DECLARE SECTION;
433   int ec, cnt;
434   char *svrname;
435   EXEC SQL END DECLARE SECTION;
436
437   svrname = argv[0];
438   EXEC SQL SELECT COUNT(service) INTO :cnt FROM serverhosts
439     WHERE service = UPPER(:svrname);
440   if (cnt > 0)
441     return MR_IN_USE;
442
443   EXEC SQL SELECT inprogress INTO :ec FROM servers
444     WHERE name = UPPER(:svrname);
445   if (dbms_errno)
446     return mr_errcode;
447   if (ec)
448     return MR_IN_USE;
449
450   return MR_SUCCESS;
451 }
452
453
454 /* setup_dshi - verify that the service-host is no longer being referenced
455  * and may safely be deleted.
456  */
457
458 int setup_dshi(struct query *q, char *argv[], client *cl)
459 {
460   EXEC SQL BEGIN DECLARE SECTION;
461   int id, ec;
462   char *svrname;
463   EXEC SQL END DECLARE SECTION;
464
465   svrname = argv[0];
466   id = *(int *)argv[1];
467
468   EXEC SQL SELECT inprogress INTO :ec FROM serverhosts
469     WHERE service = UPPER(:svrname) AND mach_id = :id;
470   if (dbms_errno)
471     return mr_errcode;
472   if (ec)
473     return MR_IN_USE;
474
475   return MR_SUCCESS;
476 }
477
478
479 /**
480  ** setup_add_filesys - verify existance of referenced file systems
481  **
482  ** Inputs:     Add
483  **   argv[1] - type
484  **   argv[2] - mach_id
485  **   argv[3] - name
486  **   argv[5] - rwaccess
487  **
488  ** Description:
489  **   - for type = RVD:
490  **        * allow anything
491  **   - for type = NFS:
492  **        * extract directory prefix from name
493  **        * verify mach_id/dir in nfsphys
494  **        * verify rwaccess in {r, w, R, W}
495  **
496  **  Side effect: sets variable _var_phys_id to the ID of the physical
497  **     filesystem (nfsphys_id for NFS, 0 for RVD)
498  **
499  ** Errors:
500  **   MR_NFS - specified directory not exported
501  **   MR_FILESYS_ACCESS - invalid filesys access
502  **
503  **/
504
505 EXEC SQL BEGIN DECLARE SECTION;
506 int _var_phys_id;
507 EXEC SQL END DECLARE SECTION;
508
509 int setup_afil(struct query *q, char *argv[], client *cl)
510 {
511   char *type, *name;
512   int mach_id;
513   EXEC SQL BEGIN DECLARE SECTION;
514   int ok;
515   char ftype[FILESYS_TYPE_SIZE + 10], *rwaccess;
516   EXEC SQL END DECLARE SECTION;
517
518   type = argv[1];
519   mach_id = *(int *)argv[2];
520   name = argv[3];
521   rwaccess = argv[5];
522   _var_phys_id = 0;
523
524   sprintf(ftype, "fs_access_%s", type);
525   EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
526     WHERE name = :ftype AND type = 'TYPE' and trans = :rwaccess;
527   if (dbms_errno)
528     return mr_errcode;
529   if (ok == 0)
530     return MR_FILESYS_ACCESS;
531
532   if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
533     return mr_errcode;
534
535   if (!strcmp(type, "NFS"))
536     return check_nfs(mach_id, name, rwaccess);
537
538   return MR_SUCCESS;
539 }
540
541
542 /* Verify the arguments, depending on the FStype.  Also, if this is an
543  * NFS filesystem, then update any quotas for that filesystem to reflect
544  * the new phys_id.
545  */
546
547 int setup_ufil(struct query *q, char *argv[], client *cl)
548 {
549   int mach_id, status;
550   char *type, *name;
551   EXEC SQL BEGIN DECLARE SECTION;
552   int fid, total, who, ok;
553   char *entity, ftype[FILESYS_TYPE_SIZE + 10], *access;
554   short int total_null;
555   EXEC SQL END DECLARE SECTION;
556
557   _var_phys_id = 0;
558   type = argv[2];
559   mach_id = *(int *)argv[3];
560   name = argv[4];
561   access = argv[6];
562   fid = *(int *)argv[0];
563   who = cl->client_id;
564   entity = cl->entity;
565
566   sprintf(ftype, "fs_access_%s", type);
567   EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
568     WHERE name = :ftype AND type = 'TYPE' AND trans = :access;
569   if (dbms_errno)
570     return mr_errcode;
571   if (ok == 0)
572     return MR_FILESYS_ACCESS;
573
574   EXEC SQL SELECT type INTO :ftype FROM filesys
575     WHERE filsys_id = :fid;
576   if (dbms_errno)
577     return mr_errcode;
578
579   if (!strcmp(type, "NFS"))
580     {
581       status = check_nfs(mach_id, name, access);
582       EXEC SQL UPDATE quota SET phys_id = :_var_phys_id
583         WHERE filsys_id = :fid;
584       if (dbms_errno)
585         return mr_errcode;
586       return status;
587     }
588   else if (!strcmp(type, "AFS") && strcmp(strtrim(ftype), "AFS")
589            && strcmp(strtrim(ftype), "ERR"))
590     {
591       total = 0;
592       EXEC SQL DELETE FROM quota
593         WHERE type = 'ANY' AND filsys_id = :fid;
594       EXEC SQL SELECT SUM (quota) INTO :total:total_null FROM quota
595         WHERE filsys_id = :fid AND phys_id != 0;
596       if (dbms_errno)
597         return mr_errcode;
598       if (!total_null && (total != 0))
599         {
600           EXEC SQL INSERT INTO quota (quota, filsys_id, phys_id, entity_id,
601                                       type, modtime, modby, modwith)
602             VALUES (:total, :fid, 0, 0, 'ANY', SYSDATE, :who, :entity);
603           if (dbms_errno)
604             return mr_errcode;
605         }
606     }
607   else
608     {
609       EXEC SQL UPDATE quota SET phys_id = 0 WHERE filsys_id = :fid;
610       if (dbms_errno)
611         return mr_errcode;
612     }
613   return MR_SUCCESS;
614 }
615
616
617 /* Find the NFS physical partition that the named directory is on.
618  * This is done by comparing the dir against the mount point of the
619  * partition.  To make sure we get the correct match when there is
620  * more than one, we sort the query in reverse order by dir name.
621  */
622
623 int check_nfs(int mach_id, char *name, char *access)
624 {
625   EXEC SQL BEGIN DECLARE SECTION;
626   char dir[NFSPHYS_DIR_SIZE];
627   int mid = mach_id;
628   EXEC SQL END DECLARE SECTION;
629   int status;
630   char *cp1;
631   char *cp2;
632
633   status = MR_NFS;
634   EXEC SQL DECLARE csr101 CURSOR FOR
635     SELECT nfsphys_id, dir FROM nfsphys
636     WHERE mach_id = :mid
637     ORDER BY 2 DESC;
638   if (dbms_errno)
639     return mr_errcode;
640   EXEC SQL OPEN csr101;
641   if (dbms_errno)
642     return mr_errcode;
643   while (1)
644     {
645       EXEC SQL FETCH csr101 INTO :_var_phys_id, :dir;
646       if (sqlca.sqlcode)
647         break;
648       cp1 = name;
649       cp2 = strtrim(dir);
650       while (*cp2)
651         {
652           if (*cp1++ != *cp2)
653             break;
654           cp2++;
655         }
656       if (!*cp2)
657         {
658           status = MR_SUCCESS;
659           break;
660         }
661     }
662   EXEC SQL CLOSE csr101;
663   if (dbms_errno)
664     return mr_errcode;
665   return status;
666 }
667
668
669 /* setup_dfil: free any quota records and fsgroup info associated with
670  * a filesystem when it is deleted.  Also adjust the allocation numbers.
671  */
672
673 int setup_dfil(struct query *q, char **argv, client *cl)
674 {
675   EXEC SQL BEGIN DECLARE SECTION;
676   int id, total, phys_id;
677   short int none;
678   EXEC SQL END DECLARE SECTION;
679
680   id = *(int *)argv[0];
681   EXEC SQL SELECT SUM (quota) INTO :total:none FROM quota
682     WHERE filsys_id = :id;
683
684   if (none)
685     total = 0;
686
687   /** What if there are multiple phys_id's per f/s? (bad data) **/
688   EXEC SQL SELECT phys_id INTO :phys_id FROM filesys
689     WHERE filsys_id = :id;
690   EXEC SQL UPDATE nfsphys SET allocated = allocated - :total
691     WHERE nfsphys_id = :phys_id;
692
693   if (!none)
694     EXEC SQL DELETE FROM quota WHERE filsys_id = :id;
695   EXEC SQL DELETE FROM fsgroup WHERE filsys_id = :id;
696   EXEC SQL DELETE FROM fsgroup WHERE group_id = :id;
697   if (dbms_errno)
698     return mr_errcode;
699   return MR_SUCCESS;
700 }
701
702
703 /* setup_dnfp: check to see that the nfs physical partition does not have
704  * any filesystems assigned to it before allowing it to be deleted.
705  */
706
707 int setup_dnfp(struct query *q, char **argv, client *cl)
708 {
709   EXEC SQL BEGIN DECLARE SECTION;
710   int id, cnt;
711   char *dir;
712   EXEC SQL END DECLARE SECTION;
713
714   id = *(int *)argv[0];
715   dir = argv[1];
716   EXEC SQL SELECT count(fs.rowid) INTO :cnt FROM filesys fs, nfsphys np
717     WHERE fs.mach_id = :id AND fs.phys_id = np.nfsphys_id
718     AND np.mach_id = :id AND np.dir = :dir;
719   if (cnt > 0)
720     return MR_IN_USE;
721   if (dbms_errno)
722     return mr_errcode;
723   return MR_SUCCESS;
724 }
725
726
727 /* setup_dqot: Remove allocation from nfsphys before deleting quota.
728  *   argv[0] = filsys_id
729  *   argv[1] = type if "update_quota" or "delete_quota"
730  *   argv[2 or 1] = users_id or list_id
731  */
732
733 int setup_dqot(struct query *q, char **argv, client *cl)
734 {
735   EXEC SQL BEGIN DECLARE SECTION;
736   int quota, fs, id, physid;
737   char *qtype;
738   EXEC SQL END DECLARE SECTION;
739
740   fs = *(int *)argv[0];
741   if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota"))
742     {
743       qtype = argv[1];
744       id = *(int *)argv[2];
745     }
746   else
747     {
748       qtype = "USER";
749       id = *(int *)argv[1];
750     }
751
752   EXEC SQL SELECT quota INTO :quota FROM quota
753     WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs;
754   EXEC SQL SELECT phys_id INTO :physid FROM filesys
755     WHERE filsys_id = :fs;
756   EXEC SQL UPDATE nfsphys SET allocated = allocated - :quota
757     WHERE nfsphys_id = :physid;
758
759   if (dbms_errno)
760     return mr_errcode;
761   return MR_SUCCESS;
762 }
763
764
765 /* prefetch_value():
766  * This routine fetches an appropriate value from the numvalues table.
767  * It is a little hack to get around the fact that SQL doesn't let you
768  * do something like INSERT INTO table (foo) VALUES (other_table.bar).
769  *
770  * It is called from the query table as (*v->pre_rtn)(q, Argv, cl) or
771  * from within a setup_...() routine with the appropriate arguments.
772  *
773  * Correct functioning of this routine may depend on the assumption
774  * that this query is an APPEND.
775  */
776
777 int prefetch_value(struct query *q, char **argv, client *cl)
778 {
779   EXEC SQL BEGIN DECLARE SECTION;
780   char *name = q->validate->object_id;
781   int value;
782   EXEC SQL END DECLARE SECTION;
783   int status, limit, argc;
784
785   /* set next object id, limiting it if necessary */
786   if (!strcmp(name, "unix_uid") || !strcmp(name, "gid"))
787     limit = 1; /* So far as I know, this isn't needed.  Just CMA. */
788   else
789     limit = 0;
790   if ((status = set_next_object_id(name, q->rtable, limit)) != MR_SUCCESS)
791     return status;
792
793   /* fetch object id */
794   EXEC SQL SELECT value INTO :value FROM numvalues WHERE name = :name;
795   if (dbms_errno)
796     return mr_errcode;
797   if (sqlca.sqlerrd[2] != 1)
798     return MR_INTERNAL;
799
800   argc = q->argc + q->vcnt;   /* end of Argv for APPENDs */
801   sprintf(argv[argc], "%d", value);
802
803   return MR_SUCCESS;
804 }
805
806 /* prefetch_filesys():
807  * Fetches the phys_id from filesys based on the filsys_id in argv[0].
808  * Appends the filsys_id and the phys_id to the argv so they can be
809  * referenced in an INSERT into a table other than filesys.  Also
810  * see comments at prefetch_value().
811  *
812  * Assumes the existence of a row where filsys_id = argv[0], since a
813  * filesys label has already been resolved to a filsys_id.
814  */
815 int prefetch_filesys(struct query *q, char **argv, client *cl)
816 {
817   EXEC SQL BEGIN DECLARE SECTION;
818   int fid, phid;
819   EXEC SQL END DECLARE SECTION;
820   int argc;
821
822   fid = *(int *)argv[0];
823   EXEC SQL SELECT phys_id INTO :phid FROM filesys WHERE filsys_id = :fid;
824   if (dbms_errno)
825     return mr_errcode;
826
827   argc = q->argc + q->vcnt;
828   sprintf(argv[argc++], "%d", phid);
829   sprintf(argv[argc], "%d", fid);
830
831   return MR_SUCCESS;
832 }
833
834
835 /* setup_ahst():
836  */
837
838 int setup_ahst(struct query *q, char **argv, client *cl)
839 {
840   EXEC SQL BEGIN DECLARE SECTION;
841   char *name, oldname[MACHINE_NAME_SIZE], vendor[MACHINE_VENDOR_SIZE];
842   char model[MACHINE_MODEL_SIZE], os[MACHINE_OS_SIZE];
843   int value, id, ssaddr, smask, shigh, slow, cnt;
844   unsigned int saddr, mask, high, low;
845   EXEC SQL END DECLARE SECTION;
846   int row;
847   struct in_addr addr;
848
849   id = *(int *)argv[0];
850
851   if (!strcmp(q->shortname, "uhst"))
852     {
853       row = 1;
854       EXEC SQL SELECT name, vendor, model, os
855         INTO :oldname, :vendor, :model, :os
856         FROM machine WHERE mach_id = :id;
857     }
858   else
859     row = 0;
860
861   if (row == 0 || strcasecmp(argv[1], oldname))
862     {
863       if (!hostname_check(argv[row]))
864         return MR_BAD_CHAR;
865     }
866
867   /* sanity check host vendor: must start with a letter, contain only
868    * letters, numerals, and hyphen, and end with an alphanumeric.
869    */
870   if (*argv[row + 1] && (row == 0 || strcasecmp(argv[2], vendor)))
871     {
872       char *p = argv[row + 1];
873
874       if (!isalpha(*p))
875         return MR_BAD_CHAR;
876       for (; *p; p++)
877         {
878           if ((!isalnum(*p) && *p != '-' && *p != '.') ||
879               (*p == '-' && p[1] == '.'))
880             return MR_BAD_CHAR;
881         }
882       if (!isalnum(*(p - 1)))
883         return MR_BAD_CHAR;
884     }
885
886   /* sanity check host type: must start with a letter, contain only
887    * letters, numerals, and hyphen, and end with an alphanumeric.
888    */
889   if (*argv[row + 2] && (row == 0 || strcasecmp(argv[3], model)))
890     {
891       char *p = argv[row + 2];
892
893       if (!isalnum(*p))
894         return MR_BAD_CHAR;
895       for (; *p; p++)
896         {
897           if ((!isalnum(*p) && *p != '-' && *p != '.') ||
898               (*p == '-' && p[1] == '.'))
899             return MR_BAD_CHAR;
900         }
901       if (!isalnum(*(p - 1)))
902         return MR_BAD_CHAR;
903     }
904
905   /* sanity check host os: must start with a letter, contain only
906    * letters, numerals, and hyphen, and end with an hyphen alphanumeric.
907    */
908   if (*argv[row + 3] && (row == 0 || strcasecmp(argv[4], os)))
909     {
910       char *p = argv[row + 3];
911
912       if (!isalpha(*p))
913         return MR_BAD_CHAR;
914       for (; *p; p++)
915         {
916           if ((!isalnum(*p) && *p != '-' && *p != '.') ||
917               (*p == '-' && p[1] == '.'))
918             return MR_BAD_CHAR;
919         }
920       if (!isalnum(*(p - 1)))
921         return MR_BAD_CHAR;
922     }
923
924   /* check for duplicate name */
925   name = argv[row];
926   EXEC SQL SELECT count(mach_id) INTO :cnt FROM hostalias
927     WHERE name = UPPER(:name);
928   if (dbms_errno)
929     return mr_errcode;
930   if (cnt != 0)
931     return MR_EXISTS;
932
933   /* check address */
934   if (!strcmp(argv[9 + row], "unassigned"))
935     value = -1;
936   else if (!strcmp(argv[9 + row], "unique"))
937     {
938       if (*(int *)argv[8 + row] == 0)
939         value = -1;
940       else
941         value = -2;
942     }
943   else
944     {
945       value = ntohl(inet_addr(argv[9 + row]));
946       if (value == -1)
947         return MR_ADDRESS;
948     }
949   if (value == 0)
950     return MR_ADDRESS;
951   if (value != -1)
952     {
953       /*
954        * an address or unique was specified.
955        */
956       id = *(int *)argv[8 + row];
957       EXEC SQL SELECT saddr, mask, high, low INTO :ssaddr, :smask,
958         :shigh, :slow FROM subnet WHERE snet_id = :id;
959       if (dbms_errno)
960         return mr_errcode;
961       saddr = (unsigned) ssaddr;
962       mask = (unsigned) smask;
963       high = (unsigned) shigh;
964       low = (unsigned) slow;
965       if (value != -2)
966         {
967           /*
968            * someone specified an IP address for the host record
969            */
970           if ((value & mask) != saddr || value < low || value > high)
971             return MR_ADDRESS;
972           /*
973            * run the address argument through inet_addr(). This
974            * has the effect that any out of bounds host addrs will
975            * be converted to a valid host addr. We do this now
976            * so that the uniqueness check works. We should also
977            * link in an inet_addr() that returns an error for
978            * this case.
979            */
980           addr.s_addr = inet_addr(argv[9 + row]);
981           name = inet_ntoa(addr);
982           EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
983             WHERE address = :name;
984           if (dbms_errno)
985             return mr_errcode;
986           if (cnt > 0)
987             {
988               /*
989                * make IP address is unique. If this a modify request
990                * (row == 1), then we expect one record to exist.
991                */
992               if (row == 0 || (row == 1 && cnt > 1))
993                 return MR_ADDRESS;
994               if (row == 1 && cnt == 1)
995                 {
996                   EXEC SQL SELECT mach_id INTO :id FROM machine
997                     WHERE address = :name;
998                   if (id != *(int *)argv[0])
999                     return MR_ADDRESS;
1000                 }
1001             }
1002         }
1003       else
1004         {
1005           /*
1006            * a "unique" address was specified. Walk through the
1007            * range specified in the network record, return
1008            * error if no room left.
1009            */
1010           for (id = low; id <= high; id++)
1011             {
1012               if (((id & 0xff) == 0) || ((id & 0xff) == 255))
1013                 continue;
1014               addr.s_addr = htonl(id);
1015               name = inet_ntoa(addr);
1016               EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
1017                 WHERE address = :name;
1018               if (dbms_errno)
1019                 return mr_errcode;
1020               if (cnt == 0)
1021                 break;
1022             }
1023           if (cnt != 0)
1024             return MR_NO_ID;
1025           else
1026             value = htonl(id);
1027         }
1028       /*
1029        * we have an address in value. Convert it to a string and store it.
1030        */
1031       addr.s_addr = htonl(value);
1032       strcpy(argv[9 + row], inet_ntoa(addr));
1033     }
1034   else
1035     strcpy(argv[9 + row], "unassigned");
1036
1037   /* status checking */
1038   value = atoi(argv[7 + row]);
1039   if (row == 0 && !(value == 1 || value == 0))
1040     return MR_TYPE;
1041   if (row == 1)
1042     {
1043       id = *(int *)argv[0];
1044       EXEC SQL SELECT status INTO :cnt FROM machine WHERE mach_id = :id;
1045       if (dbms_errno)
1046         return mr_errcode;
1047       if (value != cnt)
1048         {
1049           EXEC SQL UPDATE machine SET statuschange = SYSDATE
1050             WHERE mach_id = :id;
1051         }
1052     }
1053
1054   /*
1055    * If this is an update_host query, we're done.
1056    */
1057   if (row == 1)
1058     return MR_SUCCESS;
1059
1060   /*
1061    * For an add_host query, allocate and fill in a new machine id,
1062    * and then insert the creator id.
1063    */
1064   if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
1065     return mr_errcode;
1066
1067   sprintf(argv[q->argc + q->vcnt + 1], "%d", cl->client_id);
1068   return MR_SUCCESS;
1069 }
1070
1071
1072 /* setup_ahal():
1073  */
1074
1075 int setup_ahal(struct query *q, char **argv, client *cl)
1076 {
1077   EXEC SQL BEGIN DECLARE SECTION;
1078   char *name;
1079   int cnt;
1080   EXEC SQL END DECLARE SECTION;
1081   char *p;
1082
1083   name = argv[0];
1084   if (!hostname_check(argv[0]))
1085     return MR_BAD_CHAR;
1086
1087   EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine WHERE
1088     name = UPPER(:name);
1089   if (dbms_errno)
1090     return mr_errcode;
1091   if (cnt > 0)
1092     return MR_EXISTS;
1093
1094   return MR_SUCCESS;
1095 }
1096
1097 /* hostname_check()
1098  * validate the rfc1035-ness of a hostname
1099  */
1100
1101 int hostname_check(char *name)
1102 {
1103   char *p;
1104   int count;
1105
1106   /* sanity check name: must start with a letter, contain only
1107    * letters, numerals, and hyphen, and not end with a hyphen.
1108    * also make sure no label (the thing the .s seperate) is longer
1109    * than 63 characters.
1110    */
1111
1112   p = name;
1113   if (!isalpha(*p))
1114     return 0;
1115   count = 0;
1116   for (; *p; p++)
1117     {
1118       count++;
1119       if ((!isalnum(*p) && *p != '-' && *p != '.') ||
1120           (*p == '-' && p[1] == '.'))
1121         return 0;
1122       if (*p == '.')
1123         count = 0;
1124       if (count == 64)
1125         return 0;
1126     }
1127   if (*(p - 1) == '-')
1128     return 0;
1129   return 1;
1130 }
This page took 0.139516 seconds and 5 git commands to generate.