Annotation of libwww/Library/src/HTAABrow.c, revision 2.35

2.15      frystyk     1: /*                                                                  HTAABrow.c
2.32      frystyk     2: **     BROWSER SIDE ACCESS AUTHORIZATION MODULE
2.15      frystyk     3: **
2.19      frystyk     4: **     (c) COPYRIGHT MIT 1995.
2.15      frystyk     5: **     Please first read the full copyright statement in the file COPYRIGH.
2.35    ! frystyk     6: **     @(#) $Id: HTAABrow.c,v 2.34 1996/04/12 17:45:24 frystyk Exp $
2.1       luotonen    7: **
2.32      frystyk     8: **     Contains code for parsing challenges and creating credentials for 
                      9: **     basic and digest authentication schemes. See also the HTAAUtil module
                     10: **     for how to handle other authentication schemes. You don't have to use
                     11: **     this code at all.
2.1       luotonen   12: **
                     13: ** AUTHORS:
                     14: **     AL      Ari Luotonen    luotonen@dxcern.cern.ch
2.32      frystyk    15: **     HFN     Henrik Frystyk
2.1       luotonen   16: **
                     17: ** HISTORY:
2.5       luotonen   18: **     Oct 17  AL      Made corrections suggested by marca:
                     19: **                     Added  if (!realm->username) return NULL;
                     20: **                     Changed some ""s to NULLs.
2.33      frystyk    21: **                     Now doing HT_CALLOC() to init uuencode source;
2.5       luotonen   22: **                     otherwise HTUU_encode() reads uninitialized memory
                     23: **                     every now and then (not a real bug but not pretty).
                     24: **                     Corrected the formula for uuencode destination size.
2.32      frystyk    25: **     Feb 96 HFN      Rewritten to make it scheme independent and based on
                     26: **                     callback functions and an info structure
2.1       luotonen   27: */
                     28: 
2.17      frystyk    29: /* Library include files */
2.27      frystyk    30: #include "WWWLib.h"
                     31: #include "HTAAUtil.h"
                     32: #include "HTAABrow.h"                                   /* Implemented here */
2.1       luotonen   33: 
2.32      frystyk    34: typedef struct _HTBasic {                /* Basic challenge and credentials */
                     35:     char *     uid;
                     36:     char *     pw;
                     37: } HTBasic;
                     38: 
                     39: typedef struct _HTDigest {              /* Digest challenge and credentials */
                     40:     char *     nounce;
                     41:     char *     opaque;
                     42:     BOOL       stale;
                     43:     char *     uid;
                     44:     char *     pw;
                     45: } HTDigest;
2.7       luotonen   46: 
2.32      frystyk    47: /* ------------------------------------------------------------------------- */
2.1       luotonen   48: 
2.32      frystyk    49: /*
                     50: **     Create a protection template for the files
                     51: **     in the same directory as the given file
                     52: **     Returns a template matching docname, and other files in that directory.
                     53: **
                     54: **             E.g.  /foo/bar/x.html  =>  /foo/bar/ *
                     55: **                                                 ^
                     56: **                             Space only to prevent it from
                     57: **                             being a comment marker here,
                     58: **                             there really isn't any space.
2.1       luotonen   59: */
2.33      frystyk    60: PRIVATE char * make_template (const char * docname)
2.1       luotonen   61: {
2.32      frystyk    62:     char *tmplate = NULL;
                     63:     char *slash = NULL;
                     64:     if (docname) {
                     65:        StrAllocCopy(tmplate, docname);
                     66:        slash = strrchr(tmplate, '/');
                     67:        if (slash) slash++;
                     68:        else slash = tmplate;
                     69:        *slash = '\0';
                     70:        StrAllocCat(tmplate, "*");
                     71:     }
                     72:     else StrAllocCopy(tmplate, "*");
                     73:     if (AUTH_TRACE)
                     74:        HTTrace("Template.... Made template `%s' for file `%s'\n",
                     75:                tmplate, docname);
                     76:     return tmplate;
2.1       luotonen   77: }
                     78: 
2.32      frystyk    79: /*
                     80: **     Make basic authentication scheme credentials and register this
                     81: **     information in the request object as credentials. They will then
                     82: **     be included in the request header. An example is 
                     83: **
                     84: **             "Basic AkRDIhEF8sdEgs72F73bfaS=="
                     85: **
                     86: **     Returns YES if credentials created, else NO
                     87: */
                     88: PRIVATE HTAssocList * basic_credentials (HTRequest * request, HTBasic * basic)
                     89: {
                     90:     if (request && basic) {
                     91:        HTAssocList * credentials = HTAssocList_new();
                     92:        char * cleartext = NULL;
                     93:        char * cipher = NULL;
                     94:        int cl_len = strlen(basic->uid ? basic->uid : "") +
                     95:            strlen(basic->pw ? basic->pw : "") + 3;
                     96:        int ci_len = (4*(cl_len+2))/3;
                     97:        if ((cleartext = (char *) HT_CALLOC(1, cl_len+3)) == NULL)
                     98:            HT_OUTOFMEM("basic_credentials");
                     99:        *cleartext = '\0';
                    100:        if (basic->uid) strcpy(cleartext, basic->uid);
                    101:        strcat(cleartext, ":");
                    102:        if (basic->pw) strcat(cleartext, basic->pw);
                    103:        if ((cipher = (char *) HT_MALLOC(ci_len+1)) == NULL)
                    104:            HT_OUTOFMEM("basic_credentials");
                    105:        HTUU_encode((unsigned char *) cleartext, cl_len, cipher);
2.1       luotonen  106: 
2.32      frystyk   107:        /* Create the credentials and assign them to the request object */
                    108:        {
                    109:            int cr_len = strlen("basic") + ci_len + 2;
                    110:            char * cookie = (char *) HT_MALLOC(cr_len+1);
                    111:            if (!cookie) HT_OUTOFMEM("basic_credentials");
                    112:            strcpy(cookie, "Basic ");
                    113:            strcat(cookie, cipher);
2.35    ! frystyk   114:            HTAssocList_addObject(credentials, "Authorization", cookie);
2.32      frystyk   115:            HT_FREE(cookie);
2.1       luotonen  116:        }
2.32      frystyk   117:        HT_FREE(cleartext);
                    118:        HT_FREE(cipher);
                    119:        return credentials;
2.1       luotonen  120:     }
2.32      frystyk   121:     return NULL;
2.1       luotonen  122: }
                    123: 
2.32      frystyk   124: /*
                    125: **     Make digest authentication scheme credentials and register this
                    126: **     information in the request object as credentials. They will then
                    127: **     be included in the request header.
                    128: **     Returns YES if credentials created, else NO
                    129: */
                    130: PRIVATE HTAssocList *digest_credentials (HTRequest * request, HTDigest *digest)
                    131: {
                    132:     if (request && digest) {
                    133:        HTAssocList * credentials = HTAssocList_new();
                    134:        char * cleartext = NULL;
                    135:        char * cipher = NULL;
                    136: 
                    137:        /* Do the generation */
                    138: #if 0  
2.35    ! frystyk   139:        HTAssocList_addObject(credentials, "Authorization", cookie);
2.32      frystyk   140: #endif
                    141:        HT_FREE(cleartext);
                    142:        HT_FREE(cipher);
                    143:        return credentials;
                    144:     }
                    145:     return NULL;
2.1       luotonen  146: }
                    147: 
2.32      frystyk   148: /*
                    149: **     Prompt the user for username and password.
                    150: **     Returns YES if user name was typed in, else NO
2.1       luotonen  151: */
2.32      frystyk   152: PRIVATE BOOL prompt_user (HTRequest * request, char * realm,
                    153:                          char ** uid, char ** pw)
2.1       luotonen  154: {
2.32      frystyk   155:     HTAlertCallback * cbf = HTAlert_find(HT_A_USER_PW);
                    156:     if (request && cbf) {
                    157:        HTAlertPar * reply = HTAlert_newReply();        
                    158:        BOOL res = (*cbf)(request, HT_A_USER_PW,HT_MSG_NULL,*uid,realm,reply);
                    159:        if (res) {
                    160:            HT_FREE(*uid);
                    161:            HT_FREE(*pw);
                    162:            *uid = HTAlert_replyMessage(reply);
                    163:            *pw = HTAlert_replySecret(reply);
                    164:        }
                    165:        HTAlert_deleteReply(reply);
                    166:        return res ? YES : NO;
2.1       luotonen  167:     }
2.32      frystyk   168:     return NO;
2.1       luotonen  169: }
                    170: 
2.32      frystyk   171: /*     HTBasic_generate
                    172: **     ----------------
                    173: **     This function generates "basic" credentials for the challenge found in
                    174: **     the authentication information base for this request. The result is
                    175: **     stored as an association list in the request object.
                    176: **     This is a callback function for the AA handler.
                    177: */
2.33      frystyk   178: PUBLIC BOOL HTBasic_generate (HTRequest * request, const char * scheme,
2.32      frystyk   179:                              char * realm, void * challenge)
                    180: { 
                    181:     if (request && scheme && realm && challenge) {
                    182:        HTBasic * basic = (HTBasic *) challenge;
                    183:        if (AUTH_TRACE) HTTrace("Auth........ Generating basic credentials\n");
                    184:        /*
                    185:        ** If we have a set of credentials then store it in the request object
                    186:        */
                    187:        if (basic->uid || prompt_user(request, realm,&basic->uid,&basic->pw)) {
                    188:            HTAssocList * credentials = HTRequest_credentials(request);
                    189:            if (credentials) HTAssocList_delete(credentials);
                    190:            if ((credentials = basic_credentials(request, basic))) {
                    191:                HTRequest_setCredentials(request, credentials);
                    192:                return YES;
2.2       luotonen  193:            }
                    194:        }
2.1       luotonen  195:     }
2.32      frystyk   196:     return NO;
2.1       luotonen  197: }
                    198: 
2.32      frystyk   199: /*     HTBasic_parse
                    200: **     -------------
                    201: **     This function parses the contents of a "basic" challenge 
                    202: **     and stores the challenge in our authentication information datebase.
                    203: **     We also store the realm in the request object which will help finding
                    204: **     the right set of credentials to generate.
                    205: **     The function is a callback function for the AA handler.
                    206: */
2.33      frystyk   207: PUBLIC BOOL HTBasic_parse (HTRequest * request, const char * scheme)
2.32      frystyk   208: {
                    209:     HTAssocList * challenge;
                    210:     if (request && (challenge = HTRequest_challenge(request))) {
2.35    ! frystyk   211:        char * p = HTAssocList_findObject(challenge, "WWW-authenticate");
2.32      frystyk   212:        char * value = HTNextField(&p);
                    213:        if (AUTH_TRACE)
                    214:            HTTrace("Auth........ Parsing %s challenge\n", value?value:"NULL");
                    215:        if (p && (value = HTNextField(&p))) {
                    216:            /*
                    217:            ** If valid challenge then make a template for the resource and
                    218:            ** store this information in our authentication base
                    219:            */
                    220:            if (!strcasecomp(value, "realm") && (value = HTNextField(&p))) {
                    221:                char * url = HTAnchor_physical(HTRequest_anchor(request));
                    222:                char * tmplate = make_template(url);
                    223:                HTBasic * me = (HTBasic *) HT_CALLOC(1, sizeof(HTBasic));
                    224:                if (!me) HT_OUTOFMEM("HTBasic_parse");
                    225:                HTAuthInfo_add(scheme, tmplate, value, me);
                    226:                HTRequest_setRealm(request, value);
                    227:                HT_FREE(tmplate);
                    228:                return YES;
                    229:            }
2.1       luotonen  230:        }
                    231:     }
2.32      frystyk   232:     if (AUTH_TRACE) HTTrace("Auth........ None basic challenge found\n");
                    233:     return NO;
2.1       luotonen  234: }
                    235: 
2.32      frystyk   236: /*     HTBasic_delete
                    237: **     --------------
                    238: **     Deletes a "basic" information object
                    239: */
2.33      frystyk   240: PUBLIC BOOL HTBasic_delete (const char * scheme, void * data)
2.32      frystyk   241: {
                    242:     HTBasic * basic = (HTBasic *) data;
                    243:     if (basic) {
                    244:        HTBasic * basic = (HTBasic *) data;
                    245:        HT_FREE(basic->uid);
                    246:        HT_FREE(basic->pw);
                    247:        HT_FREE(basic);
                    248:        return YES;
2.1       luotonen  249:     }
2.32      frystyk   250:     return NO;
2.1       luotonen  251: }
                    252: 
2.32      frystyk   253: /*     HTDigest_generate
                    254: **     -----------------
                    255: **     This function generates "basic" credentials for the challenge found in
                    256: **     the authentication information base for this request. The result is
                    257: **     stored as an association list in the request object.
                    258: **     This is a callback function for the AA handler.
                    259: */
2.33      frystyk   260: PUBLIC BOOL HTDigest_generate (HTRequest * request, const char * scheme,
2.32      frystyk   261:                               char * realm, void * challenge)
                    262: { 
                    263:     if (request && scheme && realm && challenge) {
                    264:        HTDigest * digest = (HTDigest *) challenge;
                    265:        if (AUTH_TRACE)HTTrace("Auth........ Generating digest credentials\n");
                    266:        /*
                    267:        ** If we have a set of credentials then store it in the request object
                    268:        */
                    269: #if 0
                    270:        if (basic->uid || prompt_user(request, realm,&basic->uid,&basic->pw)) {
                    271:            HTAssocList * credentials = HTRequest_credentials(request);
                    272:            if (credentials) HTAssocList_delete(credentials);
                    273:            if ((credentials = basic_credentials(request, basic))) {
                    274:                HTRequest_setCredentials(request, credentials);
                    275:                return YES;
                    276:            }
2.1       luotonen  277:        }
2.32      frystyk   278: #endif
2.1       luotonen  279:     }
2.32      frystyk   280:     return NO;
2.1       luotonen  281: }
                    282: 
2.32      frystyk   283: /*     HTDigest_parse
                    284: **     --------------
                    285: **     This function parses the contents of a "digest" challenge 
                    286: **     and stores the challenge in our authentication information datebase.
                    287: **     We also store the realm in the request object which will help finding
                    288: **     the right set of credentials to generate.
                    289: **     The function is a callback function for the AA handler.
2.1       luotonen  290: */
2.33      frystyk   291: PUBLIC BOOL HTDigest_parse (HTRequest * request, const char * scheme)
2.1       luotonen  292: {
2.32      frystyk   293:     if (request) {
2.1       luotonen  294: 
2.32      frystyk   295:        /* Do the parsing */
2.1       luotonen  296: 
                    297:     }
2.32      frystyk   298:     if (AUTH_TRACE) HTTrace("Auth........ No digest challenge found\n");
2.33      frystyk   299:     return NO;
2.7       luotonen  300: }
2.1       luotonen  301: 
2.32      frystyk   302: /*     HTDigest_delete
                    303: **     ---------------
                    304: **     Deletes a "digest" information object
2.7       luotonen  305: */
2.33      frystyk   306: PUBLIC BOOL HTDigest_delete (const char * scheme, void * data)
2.1       luotonen  307: {
2.32      frystyk   308:     HTDigest * digest = (HTDigest *) data;
                    309:     if (digest) {
                    310:        HT_FREE(digest->nounce);
                    311:        HT_FREE(digest->opaque);
                    312:        HT_FREE(digest->uid);
                    313:        HT_FREE(digest->pw);
                    314:        HT_FREE(digest);
                    315:        return YES;
2.7       luotonen  316:     }
2.14      frystyk   317:     return NO;
2.7       luotonen  318: }
2.1       luotonen  319: 
                    320: 

Webmaster