/* grant.c - Novell GRANT-like DOS utility, first Client32 implementation */ #include "net.h" #include "c32ncp.h" #define GRANT_BINDERY_USER 0x0001 #define GRANT_BINDERY_GROUP 0x0002 #define NCP_RIGHT_READ 0x0001 #define NCP_RIGHT_WRITE 0x0002 #define NCP_RIGHT_OPEN 0x0004 #define NCP_RIGHT_CREATE 0x0008 #define NCP_RIGHT_DELETE 0x0010 #define NCP_RIGHT_OWNER 0x0020 #define NCP_RIGHT_SEARCH 0x0040 #define NCP_RIGHT_MODIFY 0x0080 #define NCP_RIGHT_SUPER 0x0100 #define NCP_RIGHT_ALL_386 (NCP_RIGHT_SUPER | NCP_RIGHT_READ | \ NCP_RIGHT_WRITE | NCP_RIGHT_CREATE | \ NCP_RIGHT_DELETE | NCP_RIGHT_MODIFY | \ NCP_RIGHT_SEARCH | NCP_RIGHT_OWNER) static int grant_same(char *a, char *b) { while (*a || *b) { int ca = *a++; int cb = *b++; if (ca >= 'a' && ca <= 'z') ca -= 32; if (cb >= 'a' && cb <= 'z') cb -= 32; if (ca != cb) return(0); } return(1); } static int grant_is_help(char *s) { if (!s) return(0); return(grant_same(s, "/?") || grant_same(s, "-?") || grant_same(s, "?")); } static void grant_usage_error(void) { fprintf(stdout, "Command line arguments violate grammar defined for GRANT.\n\n"); } static void grant_usage(void) { fprintf(stdout, "Usage: GRANT rightslist* [FOR path] TO [USER | GROUP] name [options]\n"); fprintf(stdout, "Options: /SubDirectories | /Files\n\n"); fprintf(stdout, "386 Rights:\n"); fprintf(stdout, "--------------------\n"); fprintf(stdout, "ALL = All\n"); fprintf(stdout, "N = No Rights\n"); fprintf(stdout, "S = Supervisor\n"); fprintf(stdout, "R = Read\n"); fprintf(stdout, "W = Write\n"); fprintf(stdout, "C = Create\n"); fprintf(stdout, "E = Erase\n"); fprintf(stdout, "M = Modify\n"); fprintf(stdout, "F = File Scan\n"); fprintf(stdout, "A = Access Control\n"); } static int grant_get_current_drive(void) { REGS regs; regs.h.ah = 0x19; int86(0x21, ®s, ®s); return((int)regs.h.al); } static int grant_current_dhandle(uint8 *connid, uint8 *dhandle) { uint8 flags = 0; int drive = grant_get_current_drive(); if (get_drive_info((uint8)drive, connid, dhandle, &flags)) return(-1); if (!*connid || (flags & 0x80)) return(-1); return(0); } static int grant_current_prefix(char *out, int max) { uint8 connid = 0; uint8 dhandle = 0; uint8 flags = 0; int drive; char server[52]; char dpath[260]; char volume[32]; char *p; int i = 0; if (!out || max < 8) return(-1); out[0] = '\0'; drive = grant_get_current_drive(); if (get_drive_info((uint8)drive, &connid, &dhandle, &flags)) return(-1); if (!connid || (flags & 0x80)) return(-1); server[0] = '\0'; if (get_fs_name(connid, server)) server[0] = '\0'; dpath[0] = '\0'; if (get_dir_path(dhandle, dpath) || !dpath[0]) return(-1); p = strchr(dpath, ':'); if (!p) return(-1); while (dpath + i < p && i < (int)sizeof(volume) - 1) { volume[i] = dpath[i]; i++; } volume[i] = '\0'; if (!volume[0]) return(-1); if (server[0]) sprintf(out, "%s/%s:", server, volume); else sprintf(out, "%s:", volume); return(0); } static void grant_upcopy(char *dst, char *src, int max) { int i = 0; if (!src) src = ""; while (*src && i < max - 1) { char c = *src++; if (c == '/') c = '\\'; if (c >= 'a' && c <= 'z') c -= 32; dst[i++] = c; } dst[i] = 0; } static void grant_basename(char *dst, char *src, int max) { char up[260]; char *p; grant_upcopy(up, src, sizeof(up)); p = strrchr(up, '\\'); if (!p) p = strrchr(up, ':'); if (p) strmaxcpy(dst, p + 1, max - 1); else strmaxcpy(dst, up, max - 1); } static void grant_header_path(char *out, char *path, int max) { char prefix[90]; char up[260]; if (grant_current_prefix(prefix, sizeof(prefix))) prefix[0] = '\0'; grant_upcopy(up, path, sizeof(up)); strmaxcpy(out, prefix, max - 1); if ((int)(strlen(out) + strlen(up)) < max - 1) strcat(out, up); } static void grant_rights_bracket(uint16 rights, char *out) { out[0] = (rights & NCP_RIGHT_SUPER) ? 'S' : ' '; out[1] = (rights & NCP_RIGHT_READ) ? 'R' : ' '; out[2] = (rights & NCP_RIGHT_WRITE) ? 'W' : ' '; out[3] = (rights & NCP_RIGHT_CREATE) ? 'C' : ' '; out[4] = (rights & NCP_RIGHT_DELETE) ? 'E' : ' '; out[5] = (rights & NCP_RIGHT_MODIFY) ? 'M' : ' '; out[6] = (rights & NCP_RIGHT_SEARCH) ? 'F' : ' '; out[7] = (rights & NCP_RIGHT_OWNER) ? 'A' : ' '; out[8] = '\0'; } static void grant_rights_string(uint16 rights, char *out) { char *p = out; if (rights == 0) { strcpy(out, "N"); return; } if ((rights & NCP_RIGHT_ALL_386) == NCP_RIGHT_ALL_386) { strcpy(out, "ALL"); return; } if (rights & NCP_RIGHT_SUPER) *p++ = 'S'; if (rights & NCP_RIGHT_READ) *p++ = 'R'; if (rights & NCP_RIGHT_WRITE) *p++ = 'W'; if (rights & NCP_RIGHT_CREATE) *p++ = 'C'; if (rights & NCP_RIGHT_DELETE) *p++ = 'E'; if (rights & NCP_RIGHT_MODIFY) *p++ = 'M'; if (rights & NCP_RIGHT_SEARCH) *p++ = 'F'; if (rights & NCP_RIGHT_OWNER) *p++ = 'A'; *p = '\0'; } static int grant_add_right_word(char *s, uint16 *rights) { if (grant_same(s, "ALL")) { *rights = NCP_RIGHT_ALL_386; return(0); } if (grant_same(s, "N") || grant_same(s, "NONE")) { *rights = 0; return(0); } if (grant_same(s, "S") || grant_same(s, "SUPERVISOR")) { *rights |= NCP_RIGHT_SUPER; return(0); } if (grant_same(s, "R") || grant_same(s, "READ")) { *rights |= NCP_RIGHT_READ; return(0); } if (grant_same(s, "W") || grant_same(s, "WRITE")) { *rights |= NCP_RIGHT_WRITE; return(0); } if (grant_same(s, "C") || grant_same(s, "CREATE")) { *rights |= NCP_RIGHT_CREATE; return(0); } if (grant_same(s, "E") || grant_same(s, "ERASE")) { *rights |= NCP_RIGHT_DELETE; return(0); } if (grant_same(s, "M") || grant_same(s, "MODIFY")) { *rights |= NCP_RIGHT_MODIFY; return(0); } if (grant_same(s, "F") || grant_same(s, "FILESCAN") || grant_same(s, "FILE") || grant_same(s, "SCAN")) { *rights |= NCP_RIGHT_SEARCH; return(0); } if (grant_same(s, "A") || grant_same(s, "ACCESS") || grant_same(s, "CONTROL") || grant_same(s, "ACCESSCONTROL")) { *rights |= NCP_RIGHT_OWNER; return(0); } return(-1); } static int grant_is_option(char *s) { if (!s) return(0); return(s[0] == '/' || s[0] == '-'); } static int grant_last_rc = 0; static int grant_set_one(char *path, uint16 dhandle, uint32 object_id, uint16 rights) { int rc; rc = c32_ncp87_add_trustee_rights(path, dhandle, object_id, rights, 0xffff, NULL, NULL, NULL); grant_last_rc = rc; return(rc); } static int grant_is_dot_dir(char *name) { if (!name) return(0); if (name[0] == '.' && name[1] == '\0') return(1); if (name[0] == '.' && name[1] == '.' && name[2] == '\0') return(1); return(0); } static void grant_join_path(char *out, char *base, char *name, int max) { int len; out[0] = '\0'; strmaxcpy(out, base, max - 1); len = strlen(out); if (len > 0 && out[len - 1] != '\\' && out[len - 1] != '/' && out[len - 1] != ':') { if (len < max - 1) { out[len++] = '\\'; out[len] = '\0'; } } if ((int)(strlen(out) + strlen(name)) < max - 1) strcat(out, name); } /* * Apply the grant to PATH and every directory below it. * * This intentionally walks through the DOS redirector, not through another * NCP search helper, so it works with the same mapped-drive view that the * user passed to GRANT. */ static int grant_set_subdirs(char *path, uint16 dhandle, uint32 object_id, uint16 rights) { struct find_t ff; char pattern[260]; char child[260]; int rc = 0; if (grant_set_one(path, dhandle, object_id, rights)) rc = 1; grant_join_path(pattern, path, "*.*", sizeof(pattern)); if (_dos_findfirst(pattern, _A_SUBDIR, &ff) == 0) { do { if ((ff.attrib & _A_SUBDIR) && !grant_is_dot_dir(ff.name)) { grant_join_path(child, path, ff.name, sizeof(child)); if (grant_set_subdirs(child, dhandle, object_id, rights)) rc = 1; } } while (_dos_findnext(&ff) == 0); } return(rc); } int func_grant(int argc, char *argv[], int mode) { uint16 rights = 0; char *path = "."; char *objname = NULL; uint16 objtype = GRANT_BINDERY_USER; uint8 connid = 0; uint8 dhandle = 0; uint8 namebuf[48]; uint32 object_id; int recurse_subdirs = 0; int i = 1; int have_rights = 0; int rc; (void)mode; if (argc < 2 || grant_is_help(argv[1])) { if (argc < 2) grant_usage_error(); grant_usage(); return(argc < 2 ? 1 : 0); } /* * GRANT rightslist* [FOR path] TO [USER|GROUP] name [options] */ while (i < argc) { if (grant_same(argv[i], "FOR") || grant_same(argv[i], "TO")) break; if (grant_is_option(argv[i])) break; if (grant_add_right_word(argv[i], &rights)) { grant_usage_error(); grant_usage(); return(1); } have_rights = 1; i++; } if (!have_rights || i >= argc) { grant_usage_error(); grant_usage(); return(1); } if (grant_same(argv[i], "FOR")) { i++; if (i >= argc) { grant_usage_error(); grant_usage(); return(1); } path = argv[i++]; } if (i >= argc || !grant_same(argv[i], "TO")) { grant_usage_error(); grant_usage(); return(1); } i++; if (i < argc && grant_same(argv[i], "USER")) { objtype = GRANT_BINDERY_USER; i++; } else if (i < argc && grant_same(argv[i], "GROUP")) { objtype = GRANT_BINDERY_GROUP; i++; } if (i >= argc) { grant_usage_error(); grant_usage(); return(1); } objname = argv[i++]; while (i < argc) { if (!grant_is_option(argv[i])) { grant_usage_error(); grant_usage(); return(1); } /* * /FILES is harmless because the explicit path is passed to the * NCP87 trustee-add call. /SUBDIRECTORIES recursively applies the * same grant to all subdirectories below the given path. */ if (grant_same(argv[i], "/FILES") || grant_same(argv[i], "-FILES") || grant_same(argv[i], "/F") || grant_same(argv[i], "-F")) { i++; continue; } if (grant_same(argv[i], "/SUBDIRECTORIES") || grant_same(argv[i], "-SUBDIRECTORIES") || grant_same(argv[i], "/S") || grant_same(argv[i], "-S")) { recurse_subdirs = 1; i++; continue; } grant_usage_error(); grant_usage(); return(1); } if (grant_current_dhandle(&connid, &dhandle)) { fprintf(stdout, "Specified path not locatable.\n"); return(1); } strmaxcpy(namebuf, objname, sizeof(namebuf) - 1); upstr(namebuf); object_id = ncp_17_35(namebuf, objtype); if (!object_id) { fprintf(stdout, "Object not found.\n"); return(1); } if (recurse_subdirs) rc = grant_set_subdirs(path, (uint16)dhandle, object_id, rights); else rc = grant_set_one(path, (uint16)dhandle, object_id, rights); if (rc) { fprintf(stdout, "Could not add trustee rights. rc=%d\n", grant_last_rc); return(grant_last_rc ? grant_last_rc : 1); } { char header[300]; char base[80]; char bracket[10]; grant_header_path(header, path, sizeof(header)); grant_basename(base, path, sizeof(base)); grant_rights_bracket(rights, bracket); fprintf(stdout, "%s\n", header); fprintf(stdout, "%-29.29sRights set to [%s]\n", base, bracket); } return(0); }