]> andersk Git - moira.git/blobdiff - server/qsetup.pc
oops, wrong argument.
[moira.git] / server / qsetup.pc
index cdb84280ab0f1aff21a1cce49560c2098d5e33e9..64e76fb655c2e4128c03fab46e36f3c0eb7b1bd0 100644 (file)
@@ -36,6 +36,7 @@ int hostname_check(char *name);
 int hostinfo_check(char *name, int num);
 int prefetch_value(struct query *q, char **argv, client *cl);
 int check_nfs(int mach_idx, char *name, char *access);
+int check_mailman_listname(char *name, const char *suffix);
 
 /* Setup Routines */
 
@@ -75,6 +76,33 @@ int setup_ausr(struct query *q, char *argv[], client *cl)
        return MR_ARG_TOO_LONG;
     }
 
+  if (q->version > 10)
+    {
+      /* For both winhomedir and winprofiledir, we allow values of the
+       * following forms:
+       *
+       * [AFS] - Magic token for AFS home directory.
+       * [LOCAL] - Magic token for AD default local values, i.e. C:\<mumble>
+       * [DFS] - Magic token for DFS home directory
+       * UNC pathname - \\<something>
+       * local pathname - <drive letter>:<something>
+       */
+
+      if ((strcasecmp(argv[row + 12], "[AFS]")) &&
+         (strcasecmp(argv[row + 12], "[LOCAL]")) &&
+         (strcasecmp(argv[row + 12], "[DFS]")) &&
+         (!(argv[row + 12][0] == '\\' && argv[row + 12][1] == '\\')) &&
+         (!(isalpha(*argv[row + 12]) && (argv[row + 12][1] == ':'))))
+       return MR_BAD_CHAR;
+      
+      if ((strcasecmp(argv[row + 13], "[AFS]")) &&
+         (strcasecmp(argv[row + 13], "[LOCAL]")) &&
+         (strcasecmp(argv[row + 13], "[DFS]")) &&
+         (!(argv[row + 13][0] == '\\' && argv[row + 13][1] == '\\')) &&
+         (!(isalpha(*argv[row + 13]) && (argv[row + 13][1] == ':'))))
+       return MR_BAD_CHAR;
+    }
+
   if (!strcmp(argv[row], UNIQUE_UID) || atoi(argv[row]) == -1)
     {
       if ((err = set_next_object_id("unix_uid", USERS_TABLE, 1)))
@@ -91,6 +119,12 @@ int setup_ausr(struct query *q, char *argv[], client *cl)
   if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
     return mr_errcode;
 
+  /* If this is an MR_Q_UPDATE query, we're done. */
+  if (row == 2)
+    return MR_SUCCESS;
+
+  /* For an add query, we need to fill in the creator id. */
+  sprintf(argv[q->argc + q->vcnt + 1], "%d", cl->client_id);
   return MR_SUCCESS;
 }
 
@@ -108,12 +142,13 @@ int setup_dusr(struct query *q, char *argv[], client *cl)
 
   id = *(int *)argv[0];
 
-  /* For now, only allow users to be deleted if their status is 0
+  /* For now, only allow users to be deleted if their status is
+   * one of 0, 4, or 8 (the various registerable statuses)
    * and we have no reservations about deleting them.
    */
   EXEC SQL SELECT status, reservations INTO :flag, :resv
     FROM users WHERE users_id = :id;
-  if ((flag != 0 && flag != 4) || *resv)
+  if ((flag != 0 && flag != 4 && flag != 8) || *resv)
     return MR_IN_USE;
 
   EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
@@ -186,6 +221,10 @@ int setup_dmac(struct query *q, char *argv[], client *cl)
     WHERE potype = 'POP' AND pop_id = :id;
   if (cnt > 0)
     return MR_IN_USE;
+  EXEC SQL SELECT COUNT(login) INTO :cnt FROM users
+    WHERE potype = 'EXCHANGE' and exchange_id = :id;
+  if (cnt > 0)
+    return MR_IN_USE;
   EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM serverhosts
     WHERE mach_id = :id;
   if (cnt > 0)
@@ -218,13 +257,70 @@ int setup_dmac(struct query *q, char *argv[], client *cl)
     WHERE mach_id = :id;
   if (cnt > 0)
     return MR_IN_USE;
+  EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
+    WHERE member_type = 'MACHINE' and member_id = :id;
+  if (cnt > 0)
+    return MR_IN_USE;
 
   EXEC SQL DELETE FROM mcmap WHERE mach_id = :id;
+  if (dbms_errno)
+    return mr_errcode;
+
+  EXEC SQL DELETE FROM mcntmap WHERE mach_id = :id;
   if (dbms_errno)
     return mr_errcode;
   return MR_SUCCESS;
 }
 
+/* setup_asnt - verify that the data entered for the subnet is sane.
+ * In particular, make sure that the "low" and "high" addresses are
+ * correctly ordered, i.e., high > low.
+ */
+
+int setup_asnt(struct query *q, char *argv[], client *cl)
+{
+  int high, low, row, status;
+  char *account_number;
+
+  /* Check for asnt or usnt. */
+  if (q->type == MR_Q_APPEND)
+    row = 0;
+  else
+    row = 1;
+
+  low = atoi(argv[row + 7]);
+  high = atoi(argv[row + 8]);
+  status = atoi(argv[row + 2]);
+  account_number = argv[row + 4];
+  
+  /* Don't allow Private subnets to be created without a valid billing
+   * number.
+   */
+  if (status == SNET_STATUS_PRIVATE_10MBPS || 
+      status == SNET_STATUS_PRIVATE_100MBPS ||
+      status == SNET_STATUS_PRIVATE_1000MBPS)
+    {
+      EXEC SQL SELECT account_number FROM accountnumbers
+       WHERE account_number = :account_number;
+      if (sqlca.sqlcode == SQL_NO_MATCH)
+       return MR_ACCOUNT_NUMBER;
+    }
+      
+  /* Special case 0.0.0.0 and 255.255.255.255 */
+  if (!(low == 0 || low == -1 || high == 0 || high == -1))
+    if (low > high)
+      return MR_ADDRESS;
+
+  /* If this is update_subnet, we're done. */
+  if (row == 1)
+    return MR_SUCCESS;
+
+  /* For an add_subnet query, allocate and fill in a new snet_id */
+  if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
+    return mr_errcode;
+
+  return MR_SUCCESS;
+}
 
 /* setup_dsnt - verify that the subnet is no longer being referenced
  * and may safely be deleted.
@@ -284,7 +380,7 @@ int setup_dclu(struct query *q, char *argv[], client *cl)
 static int badlistchars[] = {
   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
-  1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, /* SPACE - / */
+  1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, /* SPACE - / */
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */
   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */
@@ -300,27 +396,38 @@ static int badlistchars[] = {
   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 };
 
+static const char *mailman_suffixes[] = { "-admin", "-owner", "-request",
+                                         "-bounces", "-confirm", "-join",
+                                         "-leave", "-subscribe",
+                                         "-unsubscribe", NULL };
+
 int setup_alis(struct query *q, char *argv[], client *cl)
 {
   EXEC SQL BEGIN DECLARE SECTION;
-  int ngid, cnt;
+  int ngid, cnt, mailman, mailman_id, lid;
   char *name, *desc;
   EXEC SQL END DECLARE SECTION;
   unsigned char *p;
-  int idx, err;
+  int idx, err, best = -1, usage, i;
 
   if (!strcmp(q->shortname, "alis"))
     idx = 0;
   else if (!strcmp(q->shortname, "ulis"))
     idx = 1;
   name = argv[idx];
-  desc = argv[10 + idx];
+
+  if (q->version == 2)
+    desc = argv[9 + idx];
+  else if (q->version == 3)
+    desc = argv[10 + idx];
+  else if (q->version == 4)
+    desc = argv[12 + idx];
+  else if (q->version >= 10)
+    desc = argv[14 + idx];
 
   if (idx == 1)
     {
-      EXEC SQL BEGIN DECLARE SECTION;
-      int lid = *(int *)argv[0];
-      EXEC SQL END DECLARE SECTION;
+      lid = *(int *)argv[0];
 
       if (acl_access_check(lid, cl))
        return MR_PERM;
@@ -361,6 +468,89 @@ int setup_alis(struct query *q, char *argv[], client *cl)
        strcpy(argv[6 + idx], "-1");
     }
 
+  /* Don't let someone rename a list to one of the magic mailman names
+   * (foo-admin, etc) if foo already exists as a mailman list.
+   */
+  for (i = 0; mailman_suffixes[i]; i++)
+    {
+      if ((err = check_mailman_listname(name, mailman_suffixes[i])) 
+         != MR_SUCCESS)
+       return err;
+    }
+
+  if (q->version >= 10)
+    {
+      /* Don't let them take this name for a mailman list if we can't
+       * reserve the -admin, -owner, and -request names.
+       */
+      if (atoi(argv[8 + idx]))
+       {
+         EXEC SQL SELECT  COUNT(name) INTO :cnt FROM list
+           WHERE (name = :name || '-admin' OR name = :name || '-owner' OR
+                  name = :name || '-request');
+         if (cnt)
+           return MR_EXISTS;
+       }
+
+      /* Handle the [ANY] case for mailman server. */
+      mailman_id = *(int *)argv[9 + idx];
+      if (mailman_id == -1)
+       {
+         EXEC SQL DECLARE csr_mailman CURSOR FOR
+           SELECT mach_id FROM serverhosts WHERE service = 'MAILMAN'
+           AND enable = 1;
+         if (dbms_errno)
+           return mr_errcode;
+         EXEC SQL OPEN csr_mailman;
+         if (dbms_errno)
+           return mr_errcode;
+
+         while (1)
+           {
+             EXEC SQL FETCH csr_mailman INTO :mailman_id;
+             if (sqlca.sqlcode)
+               break;
+             
+             EXEC SQL SELECT COUNT(name) INTO :usage FROM list
+               WHERE mailman_id = :mailman_id;
+
+             if (best < 0 || usage < best)
+               {
+                 best = usage;
+                 *(int *)argv[9 + idx] = mailman_id;
+                 break;
+               }
+           }
+         EXEC SQL CLOSE csr_mailman;
+         if (dbms_errno)
+           return mr_errcode;
+
+         if (best == -1)
+           return MR_SERVICE;
+       }
+    }
+  else
+    {
+      /* Client too old to know about the mailman code.
+       * Use existing value of mailman boolean in the table.
+       * Don't do this for add_list from an old client, since the row
+       * they're creating won't exist yet, and there's no way for them to
+       * create a list with the mailman bit set, anyway.
+       */
+      if (idx == 1)
+       {
+         EXEC SQL SELECT mailman INTO :mailman FROM list WHERE list_id = :lid;
+         if (mailman)
+           {
+             EXEC SQL SELECT  COUNT(name) INTO :cnt FROM list
+               WHERE (name = :name || '-admin' OR name = :name || '-owner' OR
+                      name = :name || '-request');
+             if (cnt)
+               return MR_EXISTS;
+           }
+       }
+    }
+
   if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
     return mr_errcode;
 
@@ -449,6 +639,16 @@ int setup_dlis(struct query *q, char *argv[], client *cl)
   if (cnt > 0)
     return MR_IN_USE;
 
+  EXEC SQL SELECT count(name) INTO :cnt FROM containers
+    WHERE acl_id = :id AND acl_type = 'LIST';
+  if (cnt > 0)
+    return MR_IN_USE;
+
+  EXEC SQL SELECT count(name) INTO :cnt FROM containers
+    WHERE memacl_id = :id AND memacl_type = 'LIST';
+  if (cnt > 0)
+    return MR_IN_USE;
+
   return MR_SUCCESS;
 }
 
@@ -801,7 +1001,7 @@ int setup_dqot(struct query *q, char **argv, client *cl)
  * from within a setup_...() routine with the appropriate arguments.
  *
  * Correct functioning of this routine may depend on the assumption
- * that this query is an APPEND.
+ * that this query is an MR_Q_APPEND.
  */
 
 int prefetch_value(struct query *q, char **argv, client *cl)
@@ -827,7 +1027,7 @@ int prefetch_value(struct query *q, char **argv, client *cl)
   if (sqlca.sqlerrd[2] != 1)
     return MR_INTERNAL;
 
-  argc = q->argc + q->vcnt;   /* end of Argv for APPENDs */
+  argc = q->argc + q->vcnt;   /* end of Argv for MR_Q_APPENDs */
   sprintf(argv[argc], "%d", value);
 
   return MR_SUCCESS;
@@ -862,6 +1062,18 @@ int prefetch_filesys(struct query *q, char **argv, client *cl)
 }
 
 
+/* setup_ghst():
+ */
+
+int setup_ghst(struct query *q, char **argv, client *cl)
+{
+  if (strcmp(argv[0], "*") || strcmp(argv[1], "*") ||
+      strcmp(argv[2], "*") || strcmp(argv[3], "*"))
+    return MR_SUCCESS;
+  else
+    return MR_PERM;
+}
+
 /* setup_ahst():
  */
 
@@ -873,7 +1085,7 @@ int setup_ahst(struct query *q, char **argv, client *cl)
   int value, id, ssaddr, smask, shigh, slow, cnt;
   unsigned int saddr, mask, high, low;
   EXEC SQL END DECLARE SECTION;
-  int row;
+  int row, idx;
   struct in_addr addr;
 
   id = *(int *)argv[0];
@@ -888,6 +1100,13 @@ int setup_ahst(struct query *q, char **argv, client *cl)
   else
     row = 0;
 
+  if (q->version < 6)
+    idx = 0;
+  else if (q->version >= 6 && q->version < 8)
+    idx = 1;
+  else
+    idx = 2;
+
   /* Sanity check name, vendor, model, and os. */
   if ((row == 0 || strcasecmp(argv[1], oldname)) &&
       !hostname_check(argv[row]))
@@ -912,18 +1131,18 @@ int setup_ahst(struct query *q, char **argv, client *cl)
     return MR_EXISTS;
 
   /* check address */
-  if (!strcmp(argv[9 + row], "unassigned"))
+  if (!strcmp(argv[9 + row + idx], "unassigned"))
     value = -1;
-  else if (!strcmp(argv[9 + row], "unique"))
+  else if (!strcmp(argv[9 + row + idx], "unique"))
     {
-      if (*(int *)argv[8 + row] == 0)
+      if (*(int *)argv[8 + row + idx] == 0)
        value = -1;
       else
        value = -2;
     }
   else
     {
-      value = ntohl(inet_addr(argv[9 + row]));
+      value = ntohl(inet_addr(argv[9 + row + idx]));
       if (value == -1)
        return MR_ADDRESS;
     }
@@ -934,7 +1153,7 @@ int setup_ahst(struct query *q, char **argv, client *cl)
       /*
        * an address or unique was specified.
        */
-      id = *(int *)argv[8 + row];
+      id = *(int *)argv[8 + row + idx];
       EXEC SQL SELECT saddr, mask, high, low INTO :ssaddr, :smask,
        :shigh, :slow FROM subnet WHERE snet_id = :id;
       if (dbms_errno)
@@ -958,7 +1177,7 @@ int setup_ahst(struct query *q, char **argv, client *cl)
           * link in an inet_addr() that returns an error for
           * this case.
           */
-         addr.s_addr = inet_addr(argv[9 + row]);
+         addr.s_addr = inet_addr(argv[9 + row + idx]);
          name = inet_ntoa(addr);
          EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
            WHERE address = :name;
@@ -1010,13 +1229,13 @@ int setup_ahst(struct query *q, char **argv, client *cl)
        * we have an address in value. Convert it to a string and store it.
        */
       addr.s_addr = htonl(value);
-      strcpy(argv[9 + row], inet_ntoa(addr));
+      strcpy(argv[9 + row + idx], inet_ntoa(addr));
     }
   else
-    strcpy(argv[9 + row], "unassigned");
+    strcpy(argv[9 + row + idx], "unassigned");
 
   /* status checking */
-  value = atoi(argv[7 + row]);
+  value = atoi(argv[7 + row + idx]);
   if (row == 0 && !(value == 1 || value == 0))
     return MR_TYPE;
   if (row == 1)
@@ -1121,7 +1340,7 @@ int setup_aprn(struct query *q, char **argv, client *cl)
   EXEC SQL END DECLARE SECTION;
 
   /* Check for aprn or uprn. */
-  if (q->type == APPEND)
+  if (q->type == MR_Q_APPEND)
     row = 0;
   else
     row = 1;
@@ -1134,7 +1353,7 @@ int setup_aprn(struct query *q, char **argv, client *cl)
     return MR_BAD_CHAR;
   else
     {
-      if (q->type == APPEND)
+      if (q->type == MR_Q_APPEND)
        {
          EXEC SQL SELECT COUNT(name) INTO :count FROM printers
            WHERE name = :name OR duplexname = :name;
@@ -1153,7 +1372,7 @@ int setup_aprn(struct query *q, char **argv, client *cl)
 
   if (*duplexname)
     {
-      if (q->type == APPEND)
+      if (q->type == MR_Q_APPEND)
        {
          EXEC SQL SELECT COUNT(name) INTO :count FROM printers
            WHERE name = :duplexname OR duplexname = :duplexname;
@@ -1246,6 +1465,61 @@ int setup_dpsv(struct query *q, char **argv, client *cl)
   return MR_SUCCESS;
 }
 
+int setup_dcon(struct query *q, char *argv[], client *cl)
+{
+  EXEC SQL BEGIN DECLARE SECTION;
+  int id, cnt;
+  char containername[CONTAINERS_NAME_SIZE];
+  EXEC SQL END DECLARE SECTION;
+
+  id = *(int *)argv[0];
+  /* check to see if there are machines in this container */
+  EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM mcntmap
+    WHERE cnt_id = :id;
+  if (cnt > 0)
+    return MR_IN_USE;
+
+  /* check to see if there are subcontainers in this container */
+
+  /* get the container name */
+  
+  EXEC SQL SELECT name INTO :containername
+    FROM containers
+    WHERE cnt_id = :id; 
+
+  /* trim off the trailing spaces */
+   strcpy(containername, strtrim(containername));
+
+  EXEC SQL SELECT COUNT(cnt_id) INTO :cnt FROM containers
+    WHERE LOWER(name) LIKE LOWER(:containername || '/' || '%');
+
+  if (cnt > 0)
+    return MR_IN_USE;
+
+  if (dbms_errno)
+    return mr_errcode;
+  return MR_SUCCESS;
+}
+
+int setup_scli(struct query *q, char *argv[], client *cl)
+{
+  EXEC SQL BEGIN DECLARE SECTION;
+  int cnt_id, list_id;
+  EXEC SQL END DECLARE SECTION;
+
+  cnt_id = *(int *)argv[0];
+  /* Check if someone has already set the list for this container */
+  EXEC SQL SELECT list_id INTO :list_id FROM containers
+    WHERE cnt_id = :cnt_id;
+  if (list_id != 0)
+    return MR_EXISTS;
+
+  if (dbms_errno)
+    return mr_errcode;
+
+  return MR_SUCCESS;
+}
+
 /* hostname_check()
  * validate the rfc1035/rfc1123-ness of a hostname
  */
@@ -1304,3 +1578,75 @@ int hostinfo_check(char *info, int num)
   if (!isalnum(*(p - 1)))
     return 1;
 }
+
+int setup_aali(struct query *q, char *argv[], client *cl)
+{
+  EXEC SQL BEGIN DECLARE SECTION;
+  int cnt;
+  char *name, *type, *trans;
+  EXEC SQL END DECLARE SECTION;
+  name = argv[0];
+  type = argv[1];
+  trans = argv[2];
+
+  if (strcmp(strtrim(type), "FILESYS"))
+    return MR_SUCCESS;
+
+  EXEC SQL SELECT count(label) INTO :cnt FROM filesys WHERE
+    label = :name;
+  if (cnt > 0)
+    return MR_EXISTS;
+
+  return MR_SUCCESS;
+}
+
+int setup_acon(struct query *q, char *argv[], client *cl)
+{
+  EXEC SQL BEGIN DECLARE SECTION;
+  char containername[CONTAINERS_NAME_SIZE];
+  EXEC SQL END DECLARE SECTION;
+  
+  char* ptr;
+  
+  memset(containername, 0, sizeof(containername));
+  strcpy(containername, argv[0]);
+  ptr = strrchr(containername, '/');
+  /* sub container, check for parents */
+  if (ptr)
+    {
+      *ptr = '\0';
+      EXEC SQL SELECT * FROM containers
+       WHERE lower(name) = lower(:containername);      
+      if (sqlca.sqlerrd[2] != 1)
+       return MR_CONTAINER_NO_PARENT;
+    }
+  
+  if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
+    return mr_errcode;
+  
+  return MR_SUCCESS;
+}
+
+int check_mailman_listname(char *name, const char *suffix)
+{
+  char *p;
+  EXEC SQL BEGIN DECLARE SECTION;
+  int i, cnt;
+  EXEC SQL END DECLARE SECTION;
+
+  p = strstr(name, suffix);
+  if (p)
+    {
+      if (strlen(name) == (p - name + strlen(suffix)))
+       {
+         /* list is of the form "name-suffix" */
+         i = (p - name);
+         EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
+           WHERE name = SUBSTR(:name, 1, :i) AND mailman = 1;
+         if (cnt > 0)
+           return MR_EXISTS;
+       }
+    }
+
+  return MR_SUCCESS;
+}
This page took 0.057853 seconds and 4 git commands to generate.