/* * $Source$ * $Author$ * $Header$ * * Copyright (C) 1987 by the Massachusetts Institute of Technology * For copying and distribution information, please see the file * . * */ #ifndef lint static char *rcsid_qsupport_dc = "$Header$"; #endif lint #include #include "mr_server.h" #include "query.h" #include EXEC SQL INCLUDE sqlca; #include "qrtn.h" extern char *whoami; extern int dbms_errno, mr_errcode; EXEC SQL BEGIN DECLARE SECTION; extern char stmt_buf[]; EXEC SQL END DECLARE SECTION; EXEC SQL WHENEVER SQLERROR DO dbmserr(); /* Specialized Access Routines */ /* access_user - verify that client name equals specified login name * * - since field validation routines are called first, a users_id is * now in argv[0] instead of the login name. */ int access_user(q, argv, cl) struct query *q; char *argv[]; client *cl; { if (cl->users_id != *(int *)argv[0]) return(MR_PERM); else return(MR_SUCCESS); } /* access_login - verify that client name equals specified login name * * argv[0...n] contain search info. q-> */ int access_login(q, argv, cl) struct query *q; char *argv[]; client *cl; { EXEC SQL BEGIN DECLARE SECTION; int id; EXEC SQL END DECLARE SECTION; if(q->argc != 1) return MR_ARGS; if(!strcmp(q->shortname, "gual")) { EXEC SQL SELECT users_id INTO :id FROM users u, strings str WHERE u.login LIKE :argv[0] AND u.users_id != 0 AND u.comments = str.string_id; } else if (!strcmp(q->shortname, "gubl")) { EXEC SQL SELECT users_id INTO :id FROM users u WHERE u.login LIKE :argv[0] AND u.users_id != 0; } else if (!strcmp(q->shortname, "guau")) { EXEC SQL SELECT users_id INTO :id FROM users u, strings str WHERE u.unix_uid = :argv[0] AND u.users_id != 0 AND u.comments = str.string_id; } else if(!strcmp(q->shortname, "gubu")) { EXEC SQL SELECT users_id INTO :id FROM users u WHERE u.unix_uid = :argv[0] AND u.users_id != 0; } if (sqlca.sqlcode == SQL_NO_MATCH) return(MR_NO_MATCH); /* ought to be MR_USER, but this is what gual returns, so we have to be consistent */ else if (sqlca.sqlerrd[2] != 1 || id != cl->users_id) return(MR_PERM); else return(MR_SUCCESS); } /* access_list - check access for most list operations * * Inputs: argv[0] - list_id * q - query name * argv[2] - member ID (only for queries "amtl" and "dmfl") * argv[7] - group IID (only for query "ulis") * cl - client name * * - check that client is a member of the access control list * - OR, if the query is add_member_to_list or delete_member_from_list * and the list is public, allow access if client = member */ int access_list(q, argv, cl) struct query *q; char *argv[]; client *cl; { EXEC SQL BEGIN DECLARE SECTION; int list_id, acl_id, flags, gid, users_id; char acl_type[9], *newname; EXEC SQL END DECLARE SECTION; char *client_type; int client_id, status; list_id = *(int *)argv[0]; EXEC SQL SELECT acl_id, acl_type, gid, publicflg INTO :acl_id, :acl_type, :gid, :flags FROM list WHERE list_id = :list_id; if (sqlca.sqlerrd[2] != 1) return(MR_INTERNAL); /* parse client structure */ if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS) return(status); /* if amtl or dmfl and list is public allow client to add or delete self */ if (((!strcmp("amtl", q->shortname) && flags) || (!strcmp("dmfl", q->shortname))) && (!strcmp("USER", argv[1]))) { if (*(int *)argv[2] == 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 (!strcmp(argv[7], UNIQUE_GID)) { if(gid != -1) return MR_PERM; } else { if(gid != atoi(argv[7])) return MR_PERM; } newname = argv[1]; EXEC SQL SELECT users_id INTO :users_id FROM users WHERE login=:newname; if ((sqlca.sqlcode != SQL_NO_MATCH) && (users_id != client_id)) return MR_PERM; } /* check for client in access control list */ status = find_member(acl_type, acl_id, client_type, client_id); if (!status) return(MR_PERM); return(MR_SUCCESS); } /* access_visible_list - allow access to list only if it is not hidden, * or if the client is on the ACL * * Inputs: argv[0] - list_id * cl - client identifier */ int access_visible_list(q, argv, cl) struct query *q; char *argv[]; client *cl; { EXEC SQL BEGIN DECLARE SECTION; int list_id, acl_id, flags ; char acl_type[9]; EXEC SQL END DECLARE SECTION; char *client_type; int client_id, status; list_id = *(int *)argv[0]; EXEC SQL SELECT hidden, acl_id, acl_type INTO :flags, :acl_id, :acl_type FROM list WHERE list_id = :list_id; if (sqlca.sqlerrd[2] != 1) return(MR_INTERNAL); if (!flags) return(MR_SUCCESS); /* parse client structure */ if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS) return(status); /* check for client in access control list */ status = find_member(acl_type, acl_id, client_type, client_id); if (!status) return(MR_PERM); return(MR_SUCCESS); } /* access_vis_list_by_name - allow access to list only if it is not hidden, * or if the client is on the ACL * * Inputs: argv[0] - list name * cl - client identifier */ int access_vis_list_by_name(q, argv, cl) struct query *q; char *argv[]; client *cl; { EXEC SQL BEGIN DECLARE SECTION; int acl_id, flags, rowcount; char acl_type[9], *listname; EXEC SQL END DECLARE SECTION; char *client_type; int client_id, status; listname = argv[0]; EXEC SQL SELECT hidden, acl_id, acl_type INTO :flags, :acl_id, :acl_type FROM list WHERE name = :listname; rowcount=sqlca.sqlerrd[2]; if (rowcount > 1) return(MR_WILDCARD); if (rowcount == 0) return(MR_NO_MATCH); if (!flags) return(MR_SUCCESS); /* parse client structure */ if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS) return(status); /* check for client in access control list */ status = find_member(acl_type, acl_id, client_type, client_id); if (!status) return(MR_PERM); return(MR_SUCCESS); } /* access_member - allow user to access member of type "USER" and name matches * username, or to access member of type "LIST" and list is one that user is * on the acl of, or the list is visible. */ int access_member(q, argv, cl) struct query *q; char *argv[]; client *cl; { if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST")) return(access_visible_list(q, &argv[1], cl)); if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER")) { if (cl->users_id == *(int *)argv[1]) return(MR_SUCCESS); } if (!strcmp(argv[0], "KERBEROS") || !strcmp(argv[0], "RKERBERO")) { if (cl->client_id == *(int *)argv[1]) return(MR_SUCCESS); } return(MR_PERM); } /* access_qgli - special access routine for Qualified_get_lists. Allows * access iff argv[0] == "TRUE" and argv[2] == "FALSE". */ int access_qgli(q, argv, cl) struct query *q; char *argv[]; client *cl; { if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE")) return(MR_SUCCESS); return(MR_PERM); } /* access_service - allow access if user is on ACL of service. Don't * allow access if a wildcard is used. */ int access_service(q, argv, cl) struct query *q; char *argv[]; client *cl; { EXEC SQL BEGIN DECLARE SECTION; int acl_id; char *name, acl_type[9]; EXEC SQL END DECLARE SECTION; int client_id, status; char *client_type, *c; name = argv[0]; for(c=name;*c;c++) if(islower(*c)) *c = toupper(*c); /* uppercasify */ EXEC SQL SELECT acl_id, acl_type INTO :acl_id, :acl_type FROM servers WHERE name = :name; if (sqlca.sqlerrd[2] > 1) return(MR_PERM); /* parse client structure */ if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS) return(status); /* check for client in access control list */ status = find_member(acl_type, acl_id, client_type, client_id); if (!status) return(MR_PERM); return(MR_SUCCESS); } /* access_filesys - verify that client is owner or on owners list of filesystem * named by argv[0] */ int access_filesys(q, argv, cl) struct query *q; char *argv[]; client *cl; { EXEC SQL BEGIN DECLARE SECTION; int users_id, list_id; char *name; EXEC SQL END DECLARE SECTION; int status, client_id; char *client_type; name = argv[0]; EXEC SQL SELECT owner, owners INTO :users_id, :list_id FROM filesys WHERE label = :name; if (sqlca.sqlerrd[2] != 1) return(MR_PERM); if (users_id == cl->users_id) return(MR_SUCCESS); if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS) return(status); status = find_member("LIST", list_id, client_type, client_id); if (status) return(MR_SUCCESS); else return(MR_PERM); } /* access_host - successful if owner of host, or subnet containing host */ int host_access_level = 0; /* 1 for network, 2 for host */ int access_host(q, argv, cl) struct query *q; char *argv[]; client *cl; { EXEC SQL BEGIN DECLARE SECTION; int mid, sid, id; char mtype[9], stype[9]; EXEC SQL END DECLARE SECTION; int status, client_id; char *client_type; if (q->type == APPEND) { id = *(int *)argv[8]; EXEC SQL SELECT s.owner_type, s.owner_id INTO :stype, :sid FROM subnet s WHERE s.snet_id=:id; mid =0; } else if (q->type == RETRIEVE) { return(MR_SUCCESS); } else { id = *(int *)argv[0]; EXEC SQL SELECT m.owner_type, m.owner_id, s.owner_type, s.owner_id INTO :mtype, :mid, :stype, :sid FROM machine m, subnet s WHERE m.mach_id=:id and s.snet_id=m.snet_id; } if (sqlca.sqlerrd[2] != 1) return(MR_PERM); if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS) return(status); status = find_member(stype, sid, client_type, client_id); if (status) { host_access_level = 1; return(MR_SUCCESS); } status = find_member(mtype, mid, client_type, client_id); if (status) { host_access_level = 2; return(MR_SUCCESS); } else return(MR_PERM); } /* access_ahal - check for adding a host alias. * successful if host has less then 2 aliases and (client is owner of * host or subnet). * If deleting an alias, any owner will do. */ int access_ahal(q, argv, cl) struct query *q; char *argv[]; client *cl; { EXEC SQL BEGIN DECLARE SECTION; int cnt, id, mid, sid; char mtype[256], stype[256]; EXEC SQL END DECLARE SECTION; char *client_type; int status, client_id; if (q->type == RETRIEVE) return(MR_SUCCESS); id = *(int *)argv[1]; EXEC SQL SELECT count(name) INTO :cnt from hostalias WHERE mach_id = :id; if (dbms_errno) return(mr_errcode); /* if the type is 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 == APPEND && cnt >= 2) return(MR_PERM); EXEC SQL SELECT m.owner_type, m.owner_id, s.owner_type, s.owner_id INTO :mtype, :mid, :stype, :sid FROM machine m, subnet s WHERE m.mach_id=:id and s.snet_id=m.snet_id; if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS) return(status); status = find_member(mtype, mid, client_type, client_id); if (status) return(MR_SUCCESS); status = find_member(stype, sid, client_type, client_id); if (status) return(MR_SUCCESS); else return(MR_PERM); } /* access_snt - check for retrieving network structure */ int access_snt(q, argv, cl) struct query *q; char *argv[]; client *cl; { if(q->type == RETRIEVE) return(MR_SUCCESS); return(MR_PERM); }