1 #include "all.h" 2 3 static void uxfree(Unixid*); 4 5 static Unixid * xfree; 6 7 Unixidmap *idhead, *idtail; 8 9 Unixscmap *scmap; 10 11 #define UNUSED 0x7FFFFFFF 12 13 /* 14 * Sadly we have to use the IP address, since some systems (FreeBSD in particular) 15 * do not believe it to be safe to depend on the hostname and so refuse to send it. 16 * I dislike making this IP-centric, but so be it. 17 * We keep a cache of host names in getdom. 18 */ 19 Unixidmap * 20 pair2idmap(char *server, ulong clientip) 21 { 22 Resub match; 23 Unixscmap *m, *mp; 24 Unixidmap *r; 25 char dom[256]; 26 27 for(mp=0,m=scmap; m; mp=m,m=m->next){ 28 if(m->server[0] != server[0]) 29 continue; 30 if(strcmp(m->server, server)) 31 continue; 32 if(m->clientip != clientip) 33 continue; 34 if(mp){ 35 mp->next = m->next; 36 m->next = scmap; 37 scmap = m; 38 } 39 r = m->map; 40 if(r->u.timestamp != 0 && r->g.timestamp != 0) 41 return r; 42 scmap = m->next; 43 free(m); 44 break; 45 } 46 if(rpcdebug) 47 fprint(2, "looking for %lux\n", clientip); 48 if(getdom(clientip, dom, sizeof dom)<0){ 49 clog("auth: unknown ip address"); 50 return nil; 51 } 52 if(rpcdebug) 53 fprint(2, "dom is %s\n", dom); 54 for(r=idhead; r; r=r->next){ 55 if(r->u.timestamp == 0 || r->g.timestamp == 0) 56 continue; 57 match.sp = match.ep = 0; 58 if(regexec(r->sexp, server, &match, 1) == 0) 59 continue; 60 if(match.sp != server || match.ep <= match.sp || *match.ep) 61 continue; 62 match.sp = match.ep = 0; 63 if(regexec(r->cexp, dom, &match, 1) == 0) 64 continue; 65 if(match.sp != dom || match.ep <= match.sp || *match.ep) 66 continue; 67 m = malloc(sizeof(Unixscmap)); 68 m->next = scmap; 69 scmap = m; 70 m->server = strstore(server); 71 m->clientip = clientip; 72 m->map = r; 73 break; 74 } 75 return r; 76 } 77 78 int 79 readunixidmaps(char *file) 80 { 81 Waitmsg *w; 82 Biobuf *in; 83 Unixidmap *m; 84 int i, arc; char *arv[16], buf[256]; 85 char *l; 86 // long savalarm; 87 88 // savalarm = alarm(0); 89 in = Bopen(file, OREAD); 90 if(in == 0){ 91 clog("readunixidmaps can't open %s: %r\n", file); 92 // alarm(savalarm); 93 return -1; 94 } 95 for(m=idhead; m; m=m->next) 96 m->flag = 0; 97 while(l = Brdline(in, '\n')){ /* assign = */ 98 l[Blinelen(in)-1] = 0; 99 arc = strparse(l, nelem(arv), arv); 100 if(arc > 0 && arv[0][0] == '!'){ 101 ++arv[0]; 102 snprint(buf, sizeof buf, "/bin/%s", arv[0]); 103 if(chatty){ 104 chat("!"); 105 for(i=0; i<arc; i++) 106 chat(" %s", arv[i]); 107 chat("..."); 108 } 109 w = system(buf, arv); 110 if(w == nil) 111 chat("err: %r\n"); 112 else if(w->msg && w->msg[0]) 113 chat("status: %s\n", w->msg); 114 else 115 chat("OK\n"); 116 free(w); 117 continue; 118 } 119 if(arc != 4) 120 continue; 121 for(m=idhead; m; m=m->next) 122 if(strcmp(arv[0], m->server) == 0 && 123 strcmp(arv[1], m->client) == 0) 124 break; 125 if(m == 0){ 126 m = malloc(sizeof(Unixidmap)); 127 if(idtail) 128 idtail->next = m; 129 else 130 idhead = m; 131 idtail = m; 132 m->next = 0; 133 m->server = strstore(arv[0]); 134 m->client = strstore(arv[1]); 135 m->sexp = regcomp(m->server); 136 m->cexp = regcomp(m->client); 137 m->u.file = strstore(arv[2]); 138 m->u.style = 'u'; 139 m->u.timestamp = 0; 140 m->u.ids = 0; 141 m->g.file = strstore(arv[3]); 142 m->g.style = 'u'; 143 m->g.timestamp = 0; 144 m->g.ids = 0; 145 }else{ 146 if(!m->u.file || strcmp(m->u.file, arv[2]) != 0){ 147 m->u.file = strstore(arv[2]); 148 m->u.timestamp = 0; 149 } 150 if(!m->g.file || strcmp(m->g.file, arv[3]) != 0){ 151 m->g.file = strstore(arv[3]); 152 m->g.timestamp = 0; 153 } 154 } 155 m->flag = 1; 156 checkunixmap(&m->u); 157 checkunixmap(&m->g); 158 } 159 Bterm(in); 160 for(m=idhead; m; m=m->next) 161 if(m->flag == 0){ 162 m->u.file = 0; 163 m->u.timestamp = 0; 164 uxfree(m->u.ids); 165 m->u.ids = 0; 166 m->g.file = 0; 167 m->g.timestamp = 0; 168 uxfree(m->g.ids); 169 m->g.ids = 0; 170 } 171 // alarm(savalarm); 172 return 0; 173 } 174 175 static void 176 uxfree(Unixid *x) 177 { 178 Unixid *tail; 179 int count=0; 180 181 if(x){ 182 tail = x; 183 if(tail->id < 0) 184 abort(); 185 tail->id = UNUSED; 186 while(tail->next){ 187 tail = tail->next; 188 ++count; 189 if(tail->id == UNUSED) 190 abort(); 191 tail->id = UNUSED; 192 } 193 tail->next = xfree; 194 xfree = x; 195 } 196 } 197 198 int 199 checkunixmap(Unixmap *u) 200 { 201 Dir *dir; 202 203 dir = dirstat(u->file); 204 if(dir == nil){ 205 clog("checkunixmap can't stat %s: %r\n", u->file); 206 return -1; 207 } 208 if(u->timestamp > dir->mtime){ 209 free(dir); 210 return 0; 211 } 212 uxfree(u->ids); 213 u->ids = readunixids(u->file, u->style); 214 u->timestamp = time(0); 215 free(dir); 216 return 1; 217 } 218 219 int 220 name2id(Unixid **list, char *name) 221 { 222 Unixid *x, *xp; 223 224 for(xp=0,x=*list; x; xp=x,x=x->next){ 225 if(x->name[0] == name[0] && strcmp(x->name, name) == 0){ 226 if(xp){ 227 xp->next = x->next; 228 x->next = *list; 229 *list = x; 230 } 231 return x->id; 232 } 233 } 234 return -1; 235 } 236 237 char * 238 id2name(Unixid **list, int id) 239 { 240 Unixid *x, *xp; 241 242 for(xp=0,x=*list; x; xp=x,x=x->next){ 243 if(x->id == id){ 244 if(xp){ 245 xp->next = x->next; 246 x->next = *list; 247 *list = x; 248 } 249 return x->name; 250 } 251 } 252 return "none"; 253 } 254 255 void 256 idprint(int fd, Unixid *xp) 257 { 258 while(xp){ 259 fprint(fd, "%d\t%s\n", xp->id, xp->name); 260 xp = xp->next; 261 } 262 } 263 264 /* 265 * style '9': 3:tom:tom: 266 * style 'u': sysadm:*:0:0:System-Administrator:/usr/admin:/bin/sh 267 */ 268 269 Unixid * 270 readunixids(char *file, int style) 271 { 272 Biobuf *in; 273 char *l, *name = 0; 274 Unixid *x, *xp = 0; 275 int id = 0; 276 277 in = Bopen(file, OREAD); 278 if(in == 0){ 279 clog("readunixids can't open %s: %r\n", file); 280 return 0; 281 } 282 while(l = Brdline(in, '\n')){ /* assign = */ 283 l[Blinelen(in)-1] = 0; 284 switch(style){ 285 case '9': 286 id = strtol(l, &l, 10); 287 if(*l != ':') 288 continue; 289 name = ++l; 290 l = strchr(l, ':'); 291 if(l == 0) 292 continue; 293 *l = 0; 294 break; 295 case 'u': 296 name = l; 297 l = strchr(l, ':'); 298 if(l == 0) 299 continue; 300 *l++ = 0; 301 /* skip password */ 302 l = strchr(l, ':'); 303 if(l == 0) 304 continue; 305 id = strtol(l+1, 0, 10); 306 break; 307 default: 308 panic("unknown unixid style %d\n", style); 309 } 310 if(id == UNUSED) 311 id = -1; /* any value will do */ 312 if(!(x = xfree)) /* assign = */ 313 x = listalloc(1024/sizeof(Unixid), sizeof(Unixid)); 314 xfree = x->next; 315 x->id = id; 316 x->name = strstore(name); 317 x->next = xp; 318 xp = x; 319 } 320 Bterm(in); 321 return xp; 322 } 323