[28844] in Source-Commits
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,
},
{