X-Git-Url: http://andersk.mit.edu/gitweb/moira.git/blobdiff_plain/51e578b67d511788ebd44b1e49caf8cbc8d0b27a..b1919982ba281ba25d0e6bd45f09f10a8bb1a2d7:/server/qaccess.pc diff --git a/server/qaccess.pc b/server/qaccess.pc index 56d28d54..f6ea1044 100644 --- a/server/qaccess.pc +++ b/server/qaccess.pc @@ -127,34 +127,28 @@ int access_spob(struct query *q, char *argv[], client *cl) int access_list(struct query *q, char *argv[], client *cl) { EXEC SQL BEGIN DECLARE SECTION; - int list_id, acl_id, flags, gid, users_id; + int list_id, acl_id, flags, gid, users_id, member_id, member_acl_id; + int memacl_id; char acl_type[LIST_ACL_TYPE_SIZE], name[LIST_NAME_SIZE], *newname; + char member_acl_type[LIST_ACL_TYPE_SIZE], memacl_type[LIST_ACL_TYPE_SIZE]; EXEC SQL END DECLARE SECTION; int status; list_id = *(int *)argv[0]; - EXEC SQL SELECT acl_id, acl_type, gid, publicflg, name - INTO :acl_id, :acl_type, :gid, :flags, :name + member_id = *(int *)argv[2]; + EXEC SQL SELECT acl_id, acl_type, memacl_id, memacl_type, + gid, publicflg, name + INTO :acl_id, :acl_type, :memacl_id, :memacl_type, + :gid, :flags, :name FROM list WHERE list_id = :list_id; if (sqlca.sqlerrd[2] != 1) return MR_INTERNAL; - /* Allow client to add self to public list or delete self from any - * list. - */ - if ((((!strcmp("amtl", q->shortname) || - !strcmp("atml", q->shortname)) && flags) || - (!strcmp("dmfl", q->shortname)))) - { - if (!strcmp("USER", argv[1]) && *(int *)argv[2] == cl->users_id) - return MR_SUCCESS; - if (!strcmp("KERBEROS", argv[1]) && *(int *)argv[2] == -cl->client_id) - return MR_SUCCESS; - } /* if update_list, don't allow them to change the GID or rename to - a username other than their own */ - else if (!strcmp("ulis", q->shortname)) + /* if update_list, don't allow them to change the GID or rename to a + username other than their own */ + if (!strcmp("ulis", q->shortname)) { if (!strcmp(argv[7], UNIQUE_GID)) { @@ -166,7 +160,30 @@ int access_list(struct query *q, char *argv[], client *cl) if (gid != atoi(argv[7])) return MR_PERM; } + newname = argv[1]; + + if (!strcmp("ulis", q->shortname)) + { + /* Check that it doesn't conflict with the Grouper namespace. */ + if (strlen(newname) > 4 && isdigit(newname[2]) && + isdigit(newname[3]) && newname[4] == '-') + { + if (!strncasecmp(newname, "fa", 2) || + !strncasecmp(newname, "sp", 2) || + !strncasecmp(newname, "su", 2) || + !strncasecmp(newname, "ja", 2)) + return MR_RESERVED; + } + + /* Don't let anyone take owner-foo list names. They interact + * weirdly with the aliases automatically generated by + * mailhub.gen. + */ + if (!strncasecmp(newname, "owner-", 6)) + return MR_RESERVED; + } + EXEC SQL SELECT users_id INTO :users_id FROM users WHERE login = :newname; if ((sqlca.sqlcode != SQL_NO_MATCH) && strcmp(strtrim(name), newname) && @@ -174,12 +191,39 @@ int access_list(struct query *q, char *argv[], client *cl) return MR_PERM; } - /* check for client in access control list */ - status = find_member(acl_type, acl_id, cl); - if (!status) + /* check for client in access control list and return success right + * away if it's there. */ + if (find_member(acl_type, acl_id, cl)) + return MR_SUCCESS; + + /* If not amtl, atml, or dmfl, we lose. */ + if (strcmp(q->shortname, "amtl") && strcmp(q->shortname, "atml") && + strcmp(q->shortname, "dmfl") && strcmp(q->shortname, "tmol")) return MR_PERM; - return MR_SUCCESS; + if (find_member(memacl_type, memacl_id, cl)) + return MR_SUCCESS; + + if (flags || q->type == DELETE) + { + if (!strcmp("USER", argv[1]) && *(int *)argv[2] == cl->users_id) + return MR_SUCCESS; + if (!strcmp("KERBEROS", argv[1]) && *(int *)argv[2] == -cl->client_id) + return MR_SUCCESS; + if (!strcmp("LIST", argv[1]) && !strcmp("dmfl", q->shortname)) + { + EXEC SQL SELECT acl_id, acl_type INTO :member_acl_id, + :member_acl_type + FROM list + WHERE list_id = :member_id; + + if (find_member(member_acl_type, member_acl_id, cl)) + return MR_SUCCESS; + } + } + + /* Otherwise fail. */ + return MR_PERM; } @@ -193,14 +237,14 @@ int access_list(struct query *q, char *argv[], client *cl) int access_visible_list(struct query *q, char *argv[], client *cl) { EXEC SQL BEGIN DECLARE SECTION; - int list_id, acl_id, flags ; - char acl_type[LIST_ACL_TYPE_SIZE]; + int list_id, acl_id, memacl_id, flags ; + char acl_type[LIST_ACL_TYPE_SIZE], memacl_type[LIST_ACL_TYPE_SIZE]; EXEC SQL END DECLARE SECTION; int status; list_id = *(int *)argv[0]; - EXEC SQL SELECT hidden, acl_id, acl_type - INTO :flags, :acl_id, :acl_type + EXEC SQL SELECT hidden, acl_id, acl_type, memacl_id, memacl_type + INTO :flags, :acl_id, :acl_type, :memacl_id, :memacl_type FROM list WHERE list_id = :list_id; if (sqlca.sqlerrd[2] != 1) @@ -211,8 +255,11 @@ int access_visible_list(struct query *q, char *argv[], client *cl) /* check for client in access control list */ status = find_member(acl_type, acl_id, cl); if (!status) - return MR_PERM; - + { + status = find_member(memacl_type, memacl_id, cl); + if (!status) + return MR_PERM; + } return MR_SUCCESS; } @@ -227,14 +274,17 @@ int access_visible_list(struct query *q, char *argv[], client *cl) int access_vis_list_by_name(struct query *q, char *argv[], client *cl) { EXEC SQL BEGIN DECLARE SECTION; - int acl_id, flags, rowcount; - char acl_type[LIST_ACL_TYPE_SIZE], *listname; + int acl_id, memacl_id, flags, rowcount; + char acl_type[LIST_ACL_TYPE_SIZE], memacl_type[LIST_ACL_TYPE_SIZE]; + char *listname; EXEC SQL END DECLARE SECTION; int status; listname = argv[0]; - EXEC SQL SELECT hidden, acl_id, acl_type INTO :flags, :acl_id, :acl_type - FROM list WHERE name = :listname; + EXEC SQL SELECT hidden, acl_id, acl_type, memacl_id, memacl_type + INTO :flags, :acl_id, :acl_type, :memacl_id, :memacl_type + FROM list + WHERE name = :listname; rowcount = sqlca.sqlerrd[2]; if (rowcount > 1) @@ -247,8 +297,11 @@ int access_vis_list_by_name(struct query *q, char *argv[], client *cl) /* check for client in access control list */ status = find_member(acl_type, acl_id, cl); if (!status) - return MR_PERM; - + { + status = find_member(memacl_type, memacl_id, cl); + if (!status) + return MR_PERM; + } return MR_SUCCESS; } @@ -359,11 +412,19 @@ int access_filesys(struct query *q, char *argv[], client *cl) int access_host(struct query *q, char *argv[], client *cl) { EXEC SQL BEGIN DECLARE SECTION; - int mid, sid, id; + int mid, sid, id, subnet_status; char mtype[MACHINE_OWNER_TYPE_SIZE], stype[SUBNET_OWNER_TYPE_SIZE]; + char *account_number; EXEC SQL END DECLARE SECTION; - int status; + int status, idx; + if (q->version < 6) + idx = 0; + else if (q->version >= 6 && q->version < 8) + idx = 1; + else + idx = 2; + if (q->type == RETRIEVE) { if (strcmp(argv[0], "*") || strcmp(argv[1], "*") || @@ -376,19 +437,32 @@ int access_host(struct query *q, char *argv[], client *cl) if (q->type == APPEND) { /* Non-query owner must set use to zero */ - if (atoi(argv[6]) != 0) + if (atoi(argv[6 + idx]) != 0) return MR_PERM; /* ... and start the hostname with a letter */ if (isdigit(argv[0][0])) return MR_BAD_CHAR; - id = *(int *)argv[8]; - EXEC SQL SELECT s.owner_type, s.owner_id - INTO :stype, :sid FROM subnet s + id = *(int *)argv[8 + idx]; + EXEC SQL SELECT s.owner_type, s.owner_id, s.status + INTO :stype, :sid, :subnet_status FROM subnet s WHERE s.snet_id = :id; mid = 0; + /* Non query owner must provide valid billing information. */ + if (q->version >= 8) + { + if (subnet_status == SNET_STATUS_BILLABLE) + { + account_number = argv[7]; + EXEC SQL SELECT account_number FROM accountnumbers + WHERE account_number = :account_number; + if (sqlca.sqlcode == SQL_NO_MATCH) + return MR_ACCOUNT_NUMBER; + } + } + if (find_member(stype, sid, cl)) return MR_SUCCESS; else @@ -400,20 +474,36 @@ int access_host(struct query *q, char *argv[], client *cl) int status, acomment, use, ocomment, snid; char contact[MACHINE_CONTACT_SIZE], address[MACHINE_ADDRESS_SIZE]; char name[MACHINE_NAME_SIZE]; + char billing_contact[MACHINE_BILLING_CONTACT_SIZE]; EXEC SQL END DECLARE SECTION; id = *(int *)argv[0]; - EXEC SQL SELECT m.name, m.use, m.contact, m.status, m.address, - m.owner_type, m.owner_id, m.acomment, m.ocomment, m.snet_id, - s.owner_type, s.owner_id INTO :name, :use, :contact, :status, - :address, :mtype, :mid, :acomment, :ocomment, :snid, :stype, :sid + EXEC SQL SELECT m.name, m.use, m.contact, m.billing_contact, m.status, + m.address, m.owner_type, m.owner_id, m.acomment, m.ocomment, m.snet_id, + s.owner_type, s.owner_id, s.status INTO :name, :use, :contact, + :billing_contact, :status, :address, :mtype, :mid, :acomment, + :ocomment, :snid, :stype, :sid, :subnet_status FROM machine m, subnet s WHERE m.mach_id = :id AND s.snet_id = m.snet_id; if (dbms_errno) return mr_errcode; + /* Non query owner must provide valid billing information. */ + if (q->version >= 8) + { + if ((subnet_status == SNET_STATUS_BILLABLE) && + (atoi(argv[10]) != 3)) + { + account_number = argv[8]; + EXEC SQL SELECT account_number FROM accountnumbers + WHERE account_number = :account_number; + if (sqlca.sqlcode == SQL_NO_MATCH) + return MR_ACCOUNT_NUMBER; + } + } + /* non-query-owner cannot change use or ocomment */ - if ((use != atoi(argv[7])) || (ocomment != *(int *)argv[14])) + if ((use != atoi(argv[7 + idx])) || (ocomment != *(int *)argv[14 + idx])) return MR_PERM; /* or rename to start with digit */ @@ -427,18 +517,23 @@ int access_host(struct query *q, char *argv[], client *cl) /* host owner also cannot change contact, status, address, owner, or acomment */ if (strcmp(argv[6], strtrim(contact)) || - (status != atoi(argv[8])) || - strcmp(argv[10], strtrim(address)) || - strcmp(argv[11], strtrim(mtype)) || - (mid != *(int *)argv[12]) || (acomment != *(int *)argv[13])) + (status != atoi(argv[8 + idx])) || + strcmp(argv[10 + idx], strtrim(address)) || + strcmp(argv[11 + idx], strtrim(mtype)) || + (mid != *(int *)argv[12 + idx]) || + (acomment != *(int *)argv[13 + idx])) return MR_PERM; + /* Billing contact field didn't appear until version 6 */ + if (q->version >= 6) + if (strcmp(argv[7], strtrim(billing_contact))) + return MR_PERM; } else return MR_PERM; } /* If moving to a new subnet, make sure user is on acl there */ - id = *(int *)argv[9]; + id = *(int *)argv[9 + idx]; if (id != snid) { EXEC SQL SELECT owner_type, owner_id INTO :stype, :sid @@ -530,3 +625,90 @@ int access_printer(struct query *q, char *argv[], client *cl) else return MR_PERM; } + +/* access_zephyr */ +int access_zephyr(struct query *q, char *argv[], client *cl) +{ + EXEC SQL BEGIN DECLARE SECTION; + char type[ZEPHYR_OWNER_TYPE_SIZE]; + char *class; + int id; + EXEC SQL END DECLARE SECTION; + int status; + + class = argv[ZA_CLASS]; + EXEC SQL SELECT owner_type, owner_id INTO :type, :id + FROM zephyr WHERE class = :class; + if (sqlca.sqlcode) + return MR_PERM; + + status = find_member(type, id, cl); + if (status) + return MR_SUCCESS; + else + return MR_PERM; +} + +/* access_container - check access for most container operations + * + * Inputs: argv[0] - cnt_id + * q - query name + * cl - client name + * + * - check if that client is a member of the access control list + * - OR, if the query is add_machine_to_container or delete_machine_from_container + * check if the client is a memeber of the mem_acl list + * - if the query is update_container and the container is to be renamed and + * it is a top-level container, only priviledged users can do it + */ + +int access_container(struct query *q, char *argv[], client *cl) +{ + EXEC SQL BEGIN DECLARE SECTION; + int cnt_id, acl_id, memacl_id; + char acl_type[CONTAINERS_ACL_TYPE_SIZE], memacl_type[CONTAINERS_ACL_TYPE_SIZE]; + char name[CONTAINERS_NAME_SIZE], *newname; + EXEC SQL END DECLARE SECTION; + int status; + + cnt_id = *(int *)argv[0]; + + /* if amcn or dmcn, container id is the second argument */ + if (strcmp(q->shortname, "amcn") == 0 || strcmp(q->shortname, "dmcn") == 0) + cnt_id = *(int *)argv[1]; + + EXEC SQL SELECT acl_id, acl_type, memacl_id, memacl_type, name + INTO :acl_id, :acl_type, :memacl_id, :memacl_type, :name + FROM containers + WHERE cnt_id = :cnt_id; + + if (sqlca.sqlerrd[2] != 1) + return MR_INTERNAL; + + /* trim off the trailing spaces */ + strcpy(name, strtrim(name)); + + /* if the query is update_container and the containers is to be renamed + * and it is a top-level container, only dbadmin can do it */ + if (!strcmp(q->shortname, "ucon")) + { + newname = argv[1]; + if (strcmp(name, newname) && strchr(name, '/') == NULL) + return MR_PERM; + } + + /* check for client in access control list and return success right + * away if it's there. */ + if (find_member(acl_type, acl_id, cl)) + return MR_SUCCESS; + + /* If not amcn, dmcn, we lose. */ + if (strcmp(q->shortname, "amcn") && strcmp(q->shortname, "dmcn")) + return MR_PERM; + + if (find_member(memacl_type, memacl_id, cl)) + return MR_SUCCESS; + + /* Otherwise fail. */ + return MR_PERM; +}