home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / CONTRIB / HTTPD / HTTPD_SO.TAR / httpd_1.3 / src / http_auth.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-10  |  9.2 KB  |  341 lines

  1. /*
  2.  * http_auth: authentication
  3.  * 
  4.  * Rob McCool
  5.  * 
  6.  */
  7.  
  8.  
  9. #include "httpd.h"
  10.  
  11. char user[MAX_STRING_LEN];
  12.  
  13. #ifdef PEM_AUTH
  14. int doing_pem;
  15. static char pem_user[MAX_STRING_LEN];
  16. #define ENCODING_NONE -1
  17. #define ENCODING_PEM 1
  18. #define ENCODING_PGP 2
  19. #endif
  20.  
  21. void auth_bong(char *s, FILE *out) {
  22.     char errstr[MAX_STRING_LEN];
  23.  
  24. /* debugging */
  25.     if(s) {
  26.         sprintf(errstr,"%s authorization: %s",remote_name,s);
  27.         log_error(errstr);
  28.     }
  29.     if(!strcasecmp(auth_type,"Basic")) {
  30.         sprintf(errstr,"Basic realm=\"%s\"",auth_name);
  31.         die(AUTH_REQUIRED,errstr,out);
  32.     }
  33. #ifdef PEM_AUTH
  34.     if(!strcasecmp(auth_type,"PEM")) {
  35.         sprintf(errstr,"PEM entity=\"%s\"",
  36.                 auth_pem_entity);
  37.         die(AUTH_REQUIRED,errstr,out);
  38.     }
  39.     if(!strcasecmp(auth_type,"PGP")) {
  40.         sprintf(errstr,"PGP entity=\"%s\"",auth_pgp_entity);
  41.         die(AUTH_REQUIRED,errstr,out);
  42.     }
  43. #endif
  44.     else {
  45.         sprintf(errstr,"Unknown authorization method %s",auth_type);
  46.         die(SERVER_ERROR,errstr,out);
  47.     }
  48. }
  49.  
  50. void check_auth(security_data *sec, int m, FILE *out) {
  51.     char at[MAX_STRING_LEN];
  52.     char ad[MAX_STRING_LEN];
  53.     char sent_pw[MAX_STRING_LEN];
  54.     char real_pw[MAX_STRING_LEN];
  55.     char t[MAX_STRING_LEN];
  56.     char w[MAX_STRING_LEN];
  57.     char errstr[MAX_STRING_LEN];
  58.     register int x,y;
  59.     int grpstatus;
  60.  
  61.     if(!auth_type) {
  62.         sprintf(errstr,
  63. "httpd: authorization required for %s but not configured",sec->d);
  64.         die(SERVER_ERROR,errstr,out);
  65.     }
  66.  
  67.     if(!strcasecmp(auth_type,"Basic")) {
  68.         if(!auth_name) {
  69.             sprintf(errstr,"httpd: need AuthName for %s",sec->d);
  70.             die(SERVER_ERROR,errstr,out);
  71.         }
  72.         if(!auth_line[0])
  73.             auth_bong(NULL,out);
  74.         if(!auth_pwfile) {
  75.             sprintf(errstr,"httpd: need AuthUserFile for %s",sec->d);
  76.             die(SERVER_ERROR,errstr,out);
  77.         }
  78.         sscanf(auth_line,"%s %s",at,t);
  79.         if(strcmp(at,auth_type))
  80.             auth_bong("type mismatch",out);
  81.         uudecode(t,(unsigned char *)ad,MAX_STRING_LEN);
  82.         getword(user,ad,':');
  83.         strcpy(sent_pw,ad);
  84.         if(!get_pw(user,real_pw,out)) {
  85.             sprintf(errstr,"user %s not found",user);
  86.             auth_bong(errstr,out);
  87.         }
  88.         /* anyone know where the prototype for crypt is? */
  89.         if(strcmp(real_pw,(char *)crypt(sent_pw,real_pw))) {
  90.             sprintf(errstr,"user %s: password mismatch",user);
  91.             auth_bong(errstr,out);
  92.         }
  93.     }
  94. #ifdef PEM_AUTH
  95.     else if(!strcasecmp(auth_type,"PEM")) {
  96.         /* see if we're already handling the request... */
  97.         switch(doing_pem) {
  98.           case ENCODING_NONE:
  99.             auth_bong(NULL,out);
  100.           case ENCODING_PGP:
  101.             auth_bong("request with pgp for pem-protected directory",out);
  102.           default:
  103.             strcpy(user,pem_user);
  104.         }
  105.     }
  106.     else if(!strcasecmp(auth_type,"PGP")) {
  107.         switch(doing_pem) {
  108.           case ENCODING_NONE:
  109.             auth_bong(NULL,out);
  110.           case ENCODING_PEM:
  111.             auth_bong("request with pem for pgp-protected directory",out);
  112.           default:
  113.             strcpy(user,pem_user);
  114.         }
  115.         strcpy(user,pem_user);
  116.     }
  117. #endif
  118.     else {
  119.         sprintf(errstr,"unknown authorization type %s for %s",auth_type,
  120.                 sec->d);
  121.         auth_bong(errstr,out);
  122.     }
  123.  
  124.     /* Common stuff: Check for valid user */
  125.     if(auth_grpfile)
  126.         grpstatus = init_group(auth_grpfile,out);
  127.     else
  128.         grpstatus = 0;
  129.  
  130.     for(x=0;x<sec->num_auth[m];x++) {
  131.         strcpy(t,sec->auth[m][x]);
  132.         getword(w,t,' ');
  133.         if(!strcmp(w,"valid-user"))
  134.             goto found;
  135.         if(!strcmp(w,"user")) {
  136.             while(t[0]) {
  137.                 if(t[0] == '\"') {
  138.                     getword(w,&t[1],'\"');
  139.                     for(y=0;t[y];y++)
  140.                         t[y] = t[y+1];
  141.                 }
  142.                 getword(w,t,' ');
  143.                 if(!strcmp(user,w))
  144.                     goto found;
  145.             }
  146.         }
  147.         else if(!strcmp(w,"group")) {
  148.             if(!grpstatus) {
  149.                 sprintf(errstr,"group required for %s, bad groupfile",
  150.                         sec->d);
  151.                 auth_bong(errstr,out);
  152.             }
  153.             while(t[0]) {
  154.                 getword(w,t,' ');
  155.                 if(in_group(user,w))
  156.                     goto found;
  157.             }
  158.         }
  159.         else
  160.             auth_bong("require not followed by user or group",out);
  161.     }
  162.     if(grpstatus) kill_group();
  163.     sprintf(errstr,"user %s denied",user);
  164.     auth_bong(errstr,out);
  165.   found:
  166.     if(grpstatus)
  167.         kill_group();
  168. }
  169.  
  170. #ifdef PEM_AUTH
  171.  
  172. static int encrypt_pid,decrypt_pid;
  173. static char tn[L_tmpnam];
  174.  
  175. void pem_cleanup(int status, FILE *out) {
  176.     if(doing_pem != ENCODING_NONE) {
  177.         fclose(out);
  178.         waitpid(decrypt_pid,NULL,0);
  179.         waitpid(encrypt_pid,NULL,0);
  180.         unlink(tn);
  181.     }
  182. }
  183.  
  184. int decrypt_request(int sfd, char *req, FILE **out) {
  185.     int tfd,nr,pid,p[2],decrypt_fd,pem,pgp;
  186.     char w[MAX_STRING_LEN],w2[MAX_STRING_LEN];
  187.     char c;
  188.     FILE *tmp;
  189.     char *decrypt,*encrypt,*entity;
  190.  
  191.     doing_pem = ENCODING_NONE;
  192.     if(strcmp(req,"/"))
  193.         return -1;
  194.         
  195.     pem = !(strcmp(content_type,"application/x-www-pem-request"));
  196.     pgp = !(strcmp(content_type,"application/x-www-pgp-request"));
  197.  
  198.     if((!pem) && (!pgp))
  199.         return -1;
  200.  
  201.     auth_type = (pem ? "PEM" : "PGP");
  202.  
  203.     sscanf(auth_line,"%s %s",w,w2);
  204.  
  205.     if(pem) {
  206.         if(strcasecmp(w,"PEM"))
  207.             auth_bong("PEM content in reply to non-PEM request",*out);
  208.     }
  209.     else {
  210.         if(strcasecmp(w,"PGP"))
  211.             auth_bong("PGP content in reply to non-PGP request",*out);
  212.     }
  213.  
  214.     getword(w,w2,'=');
  215.     if(strcasecmp(w,"entity"))
  216.         auth_bong("Garbled entity line",*out);
  217.  
  218.     auth_type = NULL; /* prevent its being freed later */
  219.     if(w2[0] == '\"')
  220.         getword(pem_user,&w2[1],'\"');
  221.     else
  222.         strcpy(pem_user,w2);
  223.  
  224.     escape_shell_cmd(pem_user); /* protect from security threats */
  225.     if(pem) {
  226.         decrypt = auth_pem_decrypt;
  227.         encrypt = auth_pem_encrypt;
  228.         entity = auth_pem_entity;
  229.     }
  230.     else {
  231.         decrypt = auth_pgp_decrypt;
  232.         encrypt = auth_pgp_encrypt;
  233.         entity = auth_pgp_entity;
  234.     }
  235.  
  236.     if((!encrypt[0]) || (!decrypt[0]) || (!entity[0]))
  237.         die(SERVER_ERROR,"PEM/PGP authorization required but not configured",
  238.             *out);
  239.  
  240.     tmpnam(tn);
  241.     if((tfd = open(tn,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR)) == -1)
  242.         die(SERVER_ERROR,"Could not open a temp file for writing",*out);
  243.  
  244.     nr=0;
  245.     while(nr != content_length) {
  246.         char buf[1024];
  247.         int n,t;
  248.         t = content_length-nr;
  249.         if((n = read(sfd,buf,(t > 1024 ? 1024 : t))) < 1) {
  250.             close(tfd);
  251.             unlink(tn);
  252.             die(SERVER_ERROR,"Failed to read the full encrypted request",*out);
  253.         }
  254.         if(write(tfd,buf,n) != n) {
  255.             close(tfd);
  256.             unlink(tn);
  257.             die(SERVER_ERROR,"Could not write to temp file",*out);
  258.         }
  259.         nr+=n;
  260.     }
  261.     close(tfd);
  262.     /* this is done here instead of below for error recovery */
  263.     if((tfd = open(tn,O_RDONLY)) == -1) {
  264.         unlink(tn);
  265.         die(SERVER_ERROR,"Could not open temp file for reading",*out);
  266.     }
  267.  
  268.     if(pipe(p) == -1)
  269.         die(SERVER_ERROR,"Could not create IPC pipe",*out);
  270.     if((pid = fork()) == -1)
  271.         die(SERVER_ERROR,"Could not fork a new process",*out);
  272.  
  273.     if(!pid) {
  274.         char *argv0;
  275.         close(p[0]);
  276.         signal(SIGHUP,SIG_DFL);
  277.         if(tfd != STDIN_FILENO) {
  278.             dup2(tfd,STDIN_FILENO);
  279.             close(tfd);
  280.         }
  281.         if(p[1] != STDOUT_FILENO) {
  282.             dup2(p[1],STDOUT_FILENO);
  283.             close(p[1]);
  284.         }
  285.         error_log2stderr();
  286.         if(!(argv0 = strrchr(decrypt,'/')))
  287.             argv0 = decrypt;
  288.         else
  289.             ++argv0;
  290.         if(execlp(decrypt,argv0,pem_user,(char *)0) == -1)
  291.             die(SERVER_ERROR,"Could not exec decrypt command",*out); /* !!! */
  292.     }
  293.     close(tfd);
  294.     close(p[1]);
  295.     
  296.     decrypt_fd = p[0];
  297.     decrypt_pid = pid;
  298.  
  299.     /* create encryption stream */
  300.     if(pipe(p) == -1)
  301.         die(SERVER_ERROR,"Could not open an IPC pipe",*out);
  302.     if((pid = fork()) == -1)
  303.         die(SERVER_ERROR,"Could not fork new process",*out);
  304.  
  305.     if(!pid) {
  306.         char *argv0;
  307.         signal(SIGHUP,SIG_DFL);
  308.         close(p[1]);
  309.         if(fileno(*out) != STDOUT_FILENO) {
  310.             dup2(fileno(*out),STDOUT_FILENO);
  311.             fclose(*out);
  312.         }
  313.         if(p[0] != STDIN_FILENO) {
  314.             dup2(p[0],STDIN_FILENO);
  315.             close(p[0]);
  316.         }
  317.         if(!(argv0 = strrchr(encrypt,'/')))
  318.             argv0 = encrypt;
  319.         else
  320.             ++argv0;
  321.         if(execlp(encrypt,argv0,pem_user,(char*)0) == -1)
  322.             die(SERVER_ERROR,"Could not exec encrypt command",*out); /*!!!*/
  323.     }
  324.     close(p[0]);
  325.     tmp = *out;
  326.     if(!(*out = fdopen(p[1],"w")))
  327.         die(SERVER_ERROR,"Could not open stream to encrypt command",tmp);
  328.     strcpy(content_type,(pem ? "application/x-www-pem-reply" : 
  329.                          "application/x-www-pgp-reply"));
  330.     doing_pem = (pem ? ENCODING_PEM : ENCODING_PGP);
  331.     location[0] = '\0';
  332.     set_content_length(-1);
  333.     send_http_header(tmp);
  334.     fclose(tmp);
  335.  
  336.     encrypt_pid = pid;
  337.     return(decrypt_fd);
  338. }
  339.  
  340. #endif
  341.