/* bijou HTTP server for plan 9 by sean caron (scaron@umich.edu) */ #include "main.h" /* return codes: * * 0 = success * 1 = http 500 internal server error * 2 = http 401 authorization required */ int check_authorization(char *path, char *rpath, struct configuration cfg, struct request req, struct htpasswd *htpass) { Dir *td; char *u, *p, *temp; int q, j, r; uchar digest[SHA1dlen]; DigestState *s; char up[41]; temp = malloc(sizeof(char)*(strlen(path)+1)); if (temp == 0) { exits("MALLOC"); } strcpy(temp, path); if (temp[strlen(temp)-1] != '/') { for (j = strlen(temp); j > 0; j--) { if (temp[j] == '/') { temp[j+1] = '\0'; break; } } } temp = realloc(temp, sizeof(char)*(strlen(temp)+strlen(cfg.htpassfile)+2)); if (temp == 0) { exits("REALLOC"); } strcat(temp, cfg.htpassfile); while (1) { // try the path on hand td = dirstat(temp); // didnt find htpasswd file, chop the path and keep looking if (td == nil) { for (j = strlen(temp); j >= 0; j--) { if (temp[j] == '/') { temp[j] = '\0'; break; } } // if chopping off the lash slash leaves us with rpath then break out of the loop if (strcmp(temp, rpath) == 0) { break; } for (j = strlen(temp); j >= 0; j--) { if (temp[j] == '/') { temp[j+1] = '\0'; break; } } strcat(temp, cfg.htpassfile); } // found a htpasswd file, break out of this htpasswd locator loop else { break; } } // at this point, we have in temp either equal to rpath, or a path to a htpasswd file if one exists. // so basically, check to see: if temp is not rpath (contains a path to a htpasswd file) if (strcmp(temp, rpath) != 0) { // then read in the htpasswd file r = read_htpasswd_file(temp, htpass); // if the function returned with an error code, give the client a HTTP 500 internal server error if (r != 0) { free(temp); return 1; } // if we were ok, then: // split req.authorization into username and password (it should already be decoded) // username and password are colon delimited r = 0; // maybe we should make a copy of req.authorization before strtok'ing it... u = strtok(req.authorization, ":"); // this sort of error handling is really crude; this should get refactored later. if (u == 0) { free(temp); return 2; } p = strtok(0, ":"); if (p == 0) { free(temp); return 2; } // compare user name and password with entries read in from htpasswd file r = 0; for (q = 0; q < htpass->n_users; q++) { if (strcmp( u, *(htpass->user+q)) == 0) { s = sha1( (uchar *)p, strlen(p), digest, nil); sprintf(up, "%02.x%02.x%02.x%02.x%02.x%02.x%02.x%02.x%02.x%02.x%02.x%02.x%02.x%02.x%02.x%02.x%02.x%02.x%02.x%02.x", digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7], digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15], digest[16], digest[17], digest[18], digest[19] ); if (strcmp(up, *(htpass->pass+q)) == 0) { r = 1; break; } } } // if there is no match, give http 401 authorization required error if (r != 1) { free(temp); return 2; } // otherwise, success; just pass through, we will return 0 and serve up the page } free(temp); return 0; }