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

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

Webmaster