URI: 
       thttpdigest.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       thttpdigest.c (2239B)
       ---
            1 /*
            2  * HTTPDIGEST - MD5 challenge/response authentication (RFC 2617)
            3  *
            4  * Client protocol:
            5  *        write challenge: nonce method uri
            6  *        read response: 2*MD5dlen hex digits
            7  *
            8  * Server protocol:
            9  *        unimplemented
           10  */
           11 #include "std.h"
           12 #include "dat.h"
           13 
           14 static void
           15 digest(char *user, char *realm, char *passwd,
           16         char *nonce, char *method, char *uri,
           17         char *dig);
           18 
           19 static int
           20 hdclient(Conv *c)
           21 {
           22         char *realm, *passwd, *user, *f[4], *s, resp[MD5dlen*2+1];
           23         int ret;
           24         Key *k;
           25 
           26         ret = -1;
           27         s = nil;
           28 
           29         c->state = "keylookup";
           30         k = keyfetch(c, "%A", c->attr);
           31         if(k == nil)
           32                 goto out;
           33 
           34         user = strfindattr(k->attr, "user");
           35         realm = strfindattr(k->attr, "realm");
           36         passwd = strfindattr(k->attr, "!password");
           37 
           38         if(convreadm(c, &s) < 0)
           39                 goto out;
           40         if(tokenize(s, f, 4) != 3){
           41                 werrstr("bad challenge -- want nonce method uri");
           42                 goto out;
           43         }
           44 
           45         digest(user, realm, passwd, f[0], f[1], f[2], resp);
           46         convwrite(c, resp, strlen(resp));
           47         ret = 0;
           48 
           49 out:
           50         free(s);
           51         keyclose(k);
           52         return ret;
           53 }
           54 
           55 static void
           56 strtolower(char *s)
           57 {
           58         while(*s){
           59                 *s = tolower((uchar)*s);
           60                 s++;
           61         }
           62 }
           63 
           64 static void
           65 digest(char *user, char *realm, char *passwd,
           66         char *nonce, char *method, char *uri,
           67         char *dig)
           68 {
           69         uchar b[MD5dlen];
           70         char ha1[MD5dlen*2+1];
           71         char ha2[MD5dlen*2+1];
           72         DigestState *s;
           73 
           74         /*
           75          *  H(A1) = MD5(uid + ":" + realm ":" + passwd)
           76          */
           77         s = md5((uchar*)user, strlen(user), nil, nil);
           78         md5((uchar*)":", 1, nil, s);
           79         md5((uchar*)realm, strlen(realm), nil, s);
           80         md5((uchar*)":", 1, nil, s);
           81         md5((uchar*)passwd, strlen(passwd), b, s);
           82         enc16(ha1, sizeof(ha1), b, MD5dlen);
           83         strtolower(ha1);
           84 
           85         /*
           86          *  H(A2) = MD5(method + ":" + uri)
           87          */
           88         s = md5((uchar*)method, strlen(method), nil, nil);
           89         md5((uchar*)":", 1, nil, s);
           90         md5((uchar*)uri, strlen(uri), b, s);
           91         enc16(ha2, sizeof(ha2), b, MD5dlen);
           92         strtolower(ha2);
           93 
           94         /*
           95          *  digest = MD5(H(A1) + ":" + nonce + ":" + H(A2))
           96          */
           97         s = md5((uchar*)ha1, MD5dlen*2, nil, nil);
           98         md5((uchar*)":", 1, nil, s);
           99         md5((uchar*)nonce, strlen(nonce), nil, s);
          100         md5((uchar*)":", 1, nil, s);
          101         md5((uchar*)ha2, MD5dlen*2, b, s);
          102         enc16(dig, MD5dlen*2+1, b, MD5dlen);
          103         strtolower(dig);
          104 }
          105 
          106 static Role hdroles[] =
          107 {
          108         "client",        hdclient,
          109         0
          110 };
          111 
          112 Proto httpdigest =
          113 {
          114         "httpdigest",
          115         hdroles,
          116         "user? realm? !password?",
          117         0,
          118         0
          119 };