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