[28844] in Source-Commits

home help back first fref pref prev next nref lref last post

moira commit [debian]: Alias and sponsored account tweaks.

daemon@ATHENA.MIT.EDU (Anders Kaseorg)
Wed Apr 25 23:50:11 2018

Date: Wed, 25 Apr 2018 23:50:00 -0400
From: Anders Kaseorg <andersk@mit.edu>
Message-Id: <201804260350.w3Q3o0ac025407@drugstore.mit.edu>
To: source-commits@mit.edu

https://github.com/mit-athena/moira/commit/36ab666096d89cbe21f8e0158608ea6720fe447c
commit 36ab666096d89cbe21f8e0158608ea6720fe447c
Author: Garry Zacheiss <zacheiss@mit.edu>
Date:   Mon Mar 26 15:17:03 2018 -0400

    Alias and sponsored account tweaks.

 moira/clients/moira/user.c |    2 +-
 moira/server/mr_server.h   |    5 ++-
 moira/server/qaccess.pc    |   57 +++++++++++++++------
 moira/server/qrtn.pc       |    7 ++-
 moira/server/qsetup.pc     |   36 +++++++++++--
 moira/server/qsupport.pc   |  118 +++++++++++++++++++++++++++++++++++++++-----
 moira/server/queries2.c    |   81 +++++++++++++++++++++++++-----
 7 files changed, 257 insertions(+), 49 deletions(-)

diff --git a/moira/clients/moira/user.c b/moira/clients/moira/user.c
index a9b808f..6578d16 100644
--- a/moira/clients/moira/user.c
+++ b/moira/clients/moira/user.c
@@ -1300,7 +1300,7 @@ struct mqelem *GetUserBySponsor(char *type, char *name)
 
   args[0] = type;
   args[1] = name;
-  if ((status = do_mr_query("get_user_account_by_sponsor", 2, args, StoreInfo,
+  if ((status = do_mr_query("get_sponsored_user_accounts", 2, args, StoreInfo,
 			    &elem)))
     {
       com_err(program_name, status, " in get_user_account_by_sponsor");
diff --git a/moira/server/mr_server.h b/moira/server/mr_server.h
index 8a23a93..87b7f9c 100644
--- a/moira/server/mr_server.h
+++ b/moira/server/mr_server.h
@@ -70,6 +70,9 @@ extern int newqueries;
 #define MIN_VLAN_VALUE 1
 #define MAX_VLAN_VALUE 4095
 
+/* DNS constants */
+#define MAX_TTL_VALUE 2147483647
+
 /* IPv6 constants */
 #define MIN_IPV6_ADDR "::"
 #define MAX_IPV6_ADDR "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
@@ -303,7 +306,7 @@ int get_host_by_owner(struct query *q, char **argv, client *cl,
 		int (*action)(int, char *[], void *), void *actarg);
 int get_host_usage(struct query *q, char **argv, client *cl,
 		   int (*action)(int, char *[], void *), void *actarg);
-int get_user_account_by_sponsor(struct query *q, char **argv, client *cl,
+int get_sponsored_user_accounts(struct query *q, char **argv, client *cl,
 				int (*action)(int, char *[], void *),
 				void *actarg);
 int qualified_get_lists(struct query *q, char **argv, client *cl,
diff --git a/moira/server/qaccess.pc b/moira/server/qaccess.pc
index 4aacbbd..eb0d38b 100644
--- a/moira/server/qaccess.pc
+++ b/moira/server/qaccess.pc
@@ -827,15 +827,18 @@ int access_host(struct query *q, char *argv[], client *cl)
 }
 
 /* access_ahal - check for adding a host alias.
- * successful if host has less then 2 aliases and (client is owner of
- * host or subnet).
+ *
+ * successful if host has fewer then 2 aliases or is exempt from alias
+ * limit via membership on ahal capacl and user is either the host or
+ * subnet owner.
+ *
  * If deleting an alias, any owner will do.
  */
 
 int access_ahal(struct query *q, char *argv[], client *cl)
 {
   EXEC SQL BEGIN DECLARE SECTION;
-  int cnt, id, mid;
+  int cnt, id, mid, lid;
   char mtype[MACHINE_OWNER_TYPE_SIZE];
   char account_number[MACHINE_ACCOUNT_NUMBER_SIZE];
   char login[USERS_LOGIN_SIZE];
@@ -848,21 +851,43 @@ int access_ahal(struct query *q, char *argv[], client *cl)
 
   id = *(int *)argv[1];
 
-  if (q->type == MR_Q_APPEND && isdigit(argv[0][0]))
-    return MR_BAD_CHAR;
+  if (q->type == MR_Q_APPEND)
+    {
+      /* added aliases can't begin with a leading digit */
+      if (isdigit(argv[0][0]))
+	return MR_BAD_CHAR;
+
+      /* No aliases in our reserved namespace */
+      if (!strncasecmp(argv[0], "HOSTLESS-", 9))
+	return MR_RESERVED;
 
-  if (q->type == MR_Q_APPEND && !strncasecmp(argv[0], "HOSTLESS-", 9))
-    return MR_RESERVED;
+      /* Hackish, but convenient and fun: if the MACHINE record we're modifying
+       * is a member of the ahal capacl, then exempt it from the requirement that
+       * host / subnet owners can only add at most 2 aliases to records they're
+       * authorized to maintain.
+       */
 
-  EXEC SQL SELECT count(name) INTO :cnt from hostalias WHERE mach_id = :id;
-  if (dbms_errno)
-    return mr_errcode;
-  /* if the type is MR_Q_APPEND, this is ahal and we need to make sure there
-   * will be no more than 2 aliases.  If it's not, it must be dhal and
-   * any owner will do.
-   */
-  if (q->type == MR_Q_APPEND && cnt >= 2)
-    return MR_PERM;
+      /* get list_id for ahal capacl */
+      EXEC SQL SELECT list_id INTO :lid FROM capacls WHERE tag = :q->shortname;
+      if (dbms_errno)
+	return mr_errcode;
+
+      EXEC SQL SELECT COUNT(*) INTO :cnt FROM imembers WHERE list_id = :lid
+	AND member_type = 'MACHINE' and member_id = :id;
+      if (dbms_errno)
+	return mr_errcode;
+
+      /* not a member, perform access check */
+      if (cnt == 0)
+	{
+	  EXEC SQL SELECT count(name) INTO :cnt from hostalias WHERE mach_id = :id;
+	  if (dbms_errno)
+	    return mr_errcode;
+
+	  if (cnt >= 2)
+	    return MR_PERM;
+	}
+    }
 
   EXEC SQL SELECT m.owner_type, m.owner_id, m.account_number
     INTO :mtype, :mid, :account_number FROM machine m WHERE m.mach_id = :id;
diff --git a/moira/server/qrtn.pc b/moira/server/qrtn.pc
index 5b0ffc8..2032de7 100644
--- a/moira/server/qrtn.pc
+++ b/moira/server/qrtn.pc
@@ -780,7 +780,12 @@ int set_next_object_id(char *object, enum tables table, int limit)
   if (sqlca.sqlerrd[2] != 1)
     return MR_NO_ID;
 
-  starting_value = value;
+  /* current value in numvalues table has by definition been assigned.
+   * Increment it so we never reuse it.  For value types where we want
+   * reuse (limit == 1 case) we'll eventually loop back around.
+   */
+  starting_value = ++value;
+
   while (1)
     {
 #ifdef ULTRIX_ID_HOLE
diff --git a/moira/server/qsetup.pc b/moira/server/qsetup.pc
index a90549a..bfc5701 100644
--- a/moira/server/qsetup.pc
+++ b/moira/server/qsetup.pc
@@ -76,14 +76,19 @@ int setup_ausr(struct query *q, char *argv[], client *cl)
 	return MR_PERM;
     }
 
-  /* Don't allow usernames to contain anything but lower case letters,                                                
-   * numbers, or underscores.  First character must be lowercase letter.
+  /* Don't allow usernames to contain anything but lower case letters,
+   * numbers, or underscores.  First character must be lowercase letter or '#'.
    */
   if (strcmp(argv[row - 1], UNIQUE_LOGIN))
     {
-      if (!islower(argv[row - 1][0]))
+      p = argv[row - 1];
+
+      if (!islower(*p) && *p != '#')
 	return MR_BAD_CHAR;
-      for (p = argv[row - 1]; *p; p++)
+
+      /* Check rest of login name */
+      p++;
+      for (p; *p; p++)
 	{
 	  if (!(islower(*p) || isdigit(*p) || *p == '_'))
 	    return MR_BAD_CHAR;
@@ -623,6 +628,10 @@ int setup_alis(struct query *q, char *argv[], client *cl)
 	return MR_BAD_CHAR;
     }
 
+  /* Don't allow _ as a leading character */
+  if (name[0] == '_')
+    return MR_BAD_CHAR;
+
   for (p = (unsigned char *) desc; *p; p++)
     {
       if (*p == '\n')
@@ -1693,7 +1702,6 @@ int setup_uhp4(struct query *q, char **argv, client *cl)
 int setup_srrt(struct query *q, char **argv, client *cl)
 {
   char *p;
-
   if (!strcmp(argv[3], "default"))
     sprintf(argv[3], "%d", DEFAULT_TTL);
 
@@ -1704,6 +1712,9 @@ int setup_srrt(struct query *q, char **argv, client *cl)
 	return MR_INTEGER;
     }
 
+  if (atoll(argv[3]) > MAX_TTL_VALUE)
+    return MR_ARG_TOO_LONG;
+
   return MR_SUCCESS;
 }
 
@@ -2213,7 +2224,7 @@ int setup_sttl(struct query *q, char *argv[], client *cl)
 {
   EXEC SQL BEGIN DECLARE SECTION;
   int mid, count;
-  char *address;
+  char *address, *p;
   EXEC SQL END DECLARE SECTION;
 
   mid = *(int *)argv[0];
@@ -2227,6 +2238,19 @@ int setup_sttl(struct query *q, char *argv[], client *cl)
   if (count == 0)
     return MR_NO_MATCH;
 
+  if (!strcmp(argv[2], "default"))
+    sprintf(argv[2], "%d", DEFAULT_TTL);
+
+  p = argv[2];
+  for (; *p; p++)
+    {
+      if (*p < '0' || *p > '9')
+        return MR_INTEGER;
+    }
+
+  if (atoll(argv[2]) > MAX_TTL_VALUE)
+    return MR_ARG_TOO_LONG;
+
   return MR_SUCCESS;
 }
 
diff --git a/moira/server/qsupport.pc b/moira/server/qsupport.pc
index 04843b2..6f7b6bd 100644
--- a/moira/server/qsupport.pc
+++ b/moira/server/qsupport.pc
@@ -1515,6 +1515,54 @@ int get_host_usage(struct query *q, char *argv[], client *cl,
 int guas_internal(char *atype, int aid,
 		  int (*action)(int, char *[], void *), void *actarg)
 {
+  char *rargv[8], status_buf[BUFSIZ];
+  int found = 0;
+  EXEC SQL BEGIN DECLARE SECTION;
+  char *type = atype;
+  int id = aid;
+  char login[USERS_LOGIN_SIZE];
+  char first[USERS_FIRST_SIZE], last[USERS_LAST_SIZE], middle[USERS_MIDDLE_SIZE];
+  char clearid[USERS_CLEARID_SIZE], class[USERS_TYPE_SIZE], comments[STRINGS_STRING_SIZE];
+  int status;
+  EXEC SQL END DECLARE SECTION;
+
+  rargv[0] = login;
+  rargv[1] = last;
+  rargv[2] = first;
+  rargv[3] = middle;
+  rargv[4] = status_buf;
+  rargv[5] = clearid;
+  rargv[6] = class;
+  rargv[7] = comments;
+
+  EXEC SQL DECLARE csr_guas_internal CURSOR FOR
+    SELECT u.login, u.last, u.first, u.middle, u.status, u.clearid, u.type, s.string
+    FROM users u, strings s
+    WHERE u.sponsor_type = :type AND u.sponsor_id = :id AND u.users_id != 0 AND u.comments = s.string_id;
+  if (dbms_errno)
+    return mr_errcode;
+  EXEC SQL OPEN csr_guas_internal;
+  if (dbms_errno)
+    return mr_errcode;
+  while (1)
+    {
+      EXEC SQL FETCH csr_guas_internal INTO :login, :last, :first, :middle, :status, :clearid, :class, :comments;
+      if (sqlca.sqlcode)
+	break;
+      sprintf(status_buf, "%d", status);
+      (*action)(8, rargv, actarg);
+      found++;
+    }
+
+  EXEC SQL CLOSE csr_guas_internal;
+  if (!found)
+    return MR_NO_MATCH;
+  return MR_SUCCESS;
+}
+
+int gsua_internal(char *atype, int aid,
+		  int (*action)(int, char *[], void *), void *actarg)
+{
   char *rargv[1];
   int found = 0;
   EXEC SQL BEGIN DECLARE SECTION;
@@ -1547,8 +1595,8 @@ int guas_internal(char *atype, int aid,
   return MR_SUCCESS;
 }
 
-/* get_user_account_by_sponsor - like gaus but limited to user accounts */
-int get_user_account_by_sponsor(struct query *q, char *argv[], client *cl,
+/* get_sponsored_user_accounts - like gaus but limited to user accounts */
+int get_sponsored_user_accounts(struct query *q, char *argv[], client *cl,
 				int (*action)(int, char *[], void *),
 				void *actarg)
 {
@@ -1563,8 +1611,13 @@ int get_user_account_by_sponsor(struct query *q, char *argv[], client *cl,
   aid = *(int *)argv[1];
   if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") ||
       !strcmp(atype, "KERBEROS"))
-    return guas_internal(atype, aid, action, actarg);
-
+    {
+      if (!strcmp(q->shortname, "gsua"))
+	return gsua_internal(atype, aid, action, actarg);
+      else
+	return guas_internal(atype, aid, action, actarg);
+    }
+      
   sq = sq_create();
   if (!strcmp(atype, "RLIST"))
     {
@@ -1589,8 +1642,16 @@ int get_user_account_by_sponsor(struct query *q, char *argv[], client *cl,
       /* now process each one */
       while (sq_get_data(sq, &id))
 	{
-	  if (guas_internal("LIST", id, action, actarg) == MR_SUCCESS)
-	    found++;
+	  if (!strcmp(q->shortname, "gsua"))
+	    {
+	      if (gsua_internal("LIST", id, action, actarg) == MR_SUCCESS)
+		found++;
+	    }
+	  else
+	    {
+	      if (guas_internal("LIST", id, action, actarg) == MR_SUCCESS)
+		found++;
+	    }
 	}
     }
 
@@ -1615,11 +1676,27 @@ int get_user_account_by_sponsor(struct query *q, char *argv[], client *cl,
       /* now process each one */
       while (sq_get_data(sq, &id))
 	{
-	  if (guas_internal("LIST", id, action, actarg) == MR_SUCCESS)
+	  if (!strcmp(q->shortname, "gsua"))
+	    {
+	      if (gsua_internal("LIST", id, action, actarg) == MR_SUCCESS)
+		found++;
+	    }
+	  else
+	    {
+	      if (guas_internal("LIST", id, action, actarg) == MR_SUCCESS)
+		found++;
+	    }
+	}
+      if (!strcmp(q->shortname, "gsua"))
+	{
+	  if (gsua_internal("USER", aid, action, actarg) == MR_SUCCESS)
+	    found++;
+	}
+      else
+	{
+	  if (guas_internal("USER", aid, action, actarg) == MR_SUCCESS)
 	    found++;
 	}
-      if (guas_internal("USER", aid, action, actarg) == MR_SUCCESS)
-	found++;
     }
 
   if (!strcmp(atype, "RKERBEROS"))
@@ -1643,11 +1720,28 @@ int get_user_account_by_sponsor(struct query *q, char *argv[], client *cl,
       /* now process each one */
       while (sq_get_data(sq, &id))
 	{
-	  if (guas_internal("LIST", id, action, actarg) == MR_SUCCESS)
+	  if (!strcmp(q->shortname, "gsua"))
+	    {
+	      if (gsua_internal("LIST", id, action, actarg) == MR_SUCCESS)
+		found++;
+	    }
+	  else
+	    {
+	      if (guas_internal("LIST", id, action, actarg) == MR_SUCCESS)
+		found++;
+	    }
+	}
+
+      if (!strcmp(q->shortname, "gsua"))
+	{
+	  if (gsua_internal("KERBEROS", aid, action, actarg) == MR_SUCCESS)
+	    found++;
+	}
+      else
+	{
+	  if (guas_internal("KERBEROS", aid, action, actarg) == MR_SUCCESS)
 	    found++;
 	}
-      if (guas_internal("KERBEROS", aid, action, actarg) == MR_SUCCESS)
-	found++;
     }
 
   sq_destroy(sq);
diff --git a/moira/server/queries2.c b/moira/server/queries2.c
index 26384bb..74e3c7f 100644
--- a/moira/server/queries2.c
+++ b/moira/server/queries2.c
@@ -332,6 +332,29 @@ static struct validate guan_validate =
   followup_get_user,
 };
 
+static char *guas_fields[] = {
+  "sponsor_type", "sponsor_name",
+  "login", "last", "first", "middle", "status", "clearid", "class", "comments",
+};
+
+static struct valobj guas_valobj[] = {
+  {V_TYPE, 0, 0, "gaus", 0, MR_TYPE},
+  {V_TYPEDATA, 1, 0, 0, 0, MR_NO_MATCH},
+};
+
+static struct validate guas_validate =
+{
+  guas_valobj,
+  2,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  get_sponsored_user_accounts,
+};
+
 static char *guac2_fields[] = {
   "class",
   "login", "unix_uid", "shell", "last", "first", "middle", "status",
@@ -444,18 +467,18 @@ static char *guam_fields[] = {
   "affiliation_basic", "affiliation_detailed", "modtime", "modby", "modwith", "created", "creator",
 };
 
-static char *guas_fields[] = {
+static char *gsua_fields[] = {
   "sponsor_type", "sponsor_name",
   "login",
 };
 
-static struct valobj guas_valobj[] = {
+static struct valobj gsua_valobj[] = {
   {V_TYPE, 0, 0, "gaus", 0, MR_TYPE},
   {V_TYPEDATA, 1, 0, 0, 0, MR_NO_MATCH},
 };
 
-static struct validate guas_validate = {
-  guas_valobj,
+static struct validate gsua_validate = {
+  gsua_valobj,
   2,
   0,
   0,
@@ -463,7 +486,7 @@ static struct validate guas_validate = {
   0,
   access_member,
   0,
-  get_user_account_by_sponsor,
+  get_sponsored_user_accounts,
 };
 
 static char *gubu2_fields[] = {
@@ -2192,9 +2215,9 @@ static struct valobj dhid_valobj[] = {
 static struct validate dhid_validate = {
   dhid_valobj,
   3,
-  0,
-  0,
-  0,
+  "mach_id",
+  "mach_id = %d AND mach_identifier_type = UPPER('%s') AND mach_identifier = LOWER('%s')",
+  3,
   "mach_id",
   access_machidentifier,
   0,
@@ -4410,6 +4433,22 @@ static char *gpbi_fields[] = {
   "location", "contact", "modtime", "modby", "modwith"
 };
 
+static struct valobj gpbi_valobj[] = {
+  {V_TYPE, 0, 0, "mach_identifier", 0, MR_TYPE},
+};
+
+static struct validate gpbi_validate = {
+  gpbi_valobj,
+  1,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  followup_fix_modby,
+};
+
 static char *gpbh_fields[] = {
   "hostname",
   "name", "type", "hwtype", "duplexname", "duplexdefault",
@@ -5832,21 +5871,39 @@ struct query Queries[] = {
   },
 
   {
-    /* Q_GUAS - GET_USER_ACCOUNT_BY_SPONSOR, v12 */
+    /* Q_GUAS - GET_USER_ACCOUNT_BY_SPONSOR, v16 */
     "get_user_account_by_sponsor",
     "guas",
-    12,
+    16,
     MR_Q_RETRIEVE,
     0,
     0,
     0,
     guas_fields,
+    10,
+    8,
+    0,
+    2,
+    NULL,
+    &guas_validate,
+  },
+
+  {
+    /* Q_GSUA - GET_SPONSORED_USER_ACCOUNTS, v12 */
+    "get_sponsored_user_accounts",
+    "gsua",
+    12,
+    MR_Q_RETRIEVE,
+    0,
+    0,
+    0,
+    gsua_fields,
     3,
     1,
     0,
     2,
     NULL,
-    &guas_validate,
+    &gsua_validate,
   },
 
   {
@@ -9872,7 +9929,7 @@ struct query Queries[] = {
     "midmap.mach_identifier_type LIKE '%s' AND midmap.mach_identifier LIKE LOWER('%s') AND midmap.mach_id = m1.mach_id AND m1.mach_id = pr.mach_id AND m2.mach_id = pr.loghost AND m3.mach_id = pr.rm AND m4.mach_id = pr.rq AND l1.list_id = pr.ac AND l2.list_id = pr.lpc_acl AND l3.list_id = pr.report_list",
     2,
     "pr.name",
-    &VDfix_modby,
+    &gpbi_validate,
   },
 
   {

home help back first fref pref prev next nref lref last post