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

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.36    ! frystyk     6: **     @(#) $Id: HTAABrow.c,v 2.35 1996/07/02 22:54:07 frystyk Exp $
2.1       luotonen    7: **
2.32      frystyk     8: **     Contains code for parsing challenges and creating credentials for 
2.36    ! frystyk     9: **     basic authentication schemes. See also the HTAAUtil module
2.32      frystyk    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.36    ! frystyk    34: #define BASIC_AUTH     "basic"
        !            35: 
2.32      frystyk    36: typedef struct _HTBasic {                /* Basic challenge and credentials */
                     37:     char *     uid;
                     38:     char *     pw;
2.36    ! frystyk    39:     BOOL       first;
2.32      frystyk    40: } HTBasic;
                     41: 
2.36    ! frystyk    42: /* ------------------------------------------------------------------------- */
        !            43: 
        !            44: PRIVATE HTBasic * HTBasic_new()
        !            45: {
        !            46:     HTBasic * me = NULL;
        !            47:     if ((me = (HTBasic *) HT_CALLOC(1, sizeof(HTBasic))) == NULL)
        !            48:        HT_OUTOFMEM("HTBasic_new");
        !            49:     me->first = YES;
        !            50:     return me;
        !            51: }
2.7       luotonen   52: 
2.36    ! frystyk    53: /*     HTBasic_delete
        !            54: **     --------------
        !            55: **     Deletes a "basic" information object
        !            56: */
        !            57: PUBLIC int HTBasic_delete (void * context)
        !            58: {
        !            59:     HTBasic * basic = (HTBasic *) context;
        !            60:     if (basic) {
        !            61:        HT_FREE(basic->uid);
        !            62:        HT_FREE(basic->pw);
        !            63:        HT_FREE(basic);
        !            64:        return YES;
        !            65:     }
        !            66:     return NO;
        !            67: }
2.1       luotonen   68: 
2.32      frystyk    69: /*
                     70: **     Create a protection template for the files
                     71: **     in the same directory as the given file
                     72: **     Returns a template matching docname, and other files in that directory.
                     73: **
                     74: **             E.g.  /foo/bar/x.html  =>  /foo/bar/ *
                     75: **                                                 ^
                     76: **                             Space only to prevent it from
                     77: **                             being a comment marker here,
                     78: **                             there really isn't any space.
2.1       luotonen   79: */
2.33      frystyk    80: PRIVATE char * make_template (const char * docname)
2.1       luotonen   81: {
2.32      frystyk    82:     char *tmplate = NULL;
                     83:     char *slash = NULL;
                     84:     if (docname) {
                     85:        StrAllocCopy(tmplate, docname);
                     86:        slash = strrchr(tmplate, '/');
                     87:        if (slash) slash++;
                     88:        else slash = tmplate;
                     89:        *slash = '\0';
                     90:        StrAllocCat(tmplate, "*");
                     91:     }
                     92:     else StrAllocCopy(tmplate, "*");
                     93:     if (AUTH_TRACE)
                     94:        HTTrace("Template.... Made template `%s' for file `%s'\n",
                     95:                tmplate, docname);
                     96:     return tmplate;
2.1       luotonen   97: }
                     98: 
2.32      frystyk    99: /*
                    100: **     Make basic authentication scheme credentials and register this
                    101: **     information in the request object as credentials. They will then
                    102: **     be included in the request header. An example is 
                    103: **
                    104: **             "Basic AkRDIhEF8sdEgs72F73bfaS=="
                    105: **
2.36    ! frystyk   106: **     Returns HT_OK or HT_ERROR
2.32      frystyk   107: */
2.36    ! frystyk   108: PRIVATE BOOL basic_credentials (HTRequest * request, HTBasic * basic)
2.32      frystyk   109: {
                    110:     if (request && basic) {
                    111:        char * cleartext = NULL;
                    112:        char * cipher = NULL;
                    113:        int cl_len = strlen(basic->uid ? basic->uid : "") +
                    114:            strlen(basic->pw ? basic->pw : "") + 3;
                    115:        int ci_len = (4*(cl_len+2))/3;
                    116:        if ((cleartext = (char *) HT_CALLOC(1, cl_len+3)) == NULL)
                    117:            HT_OUTOFMEM("basic_credentials");
                    118:        *cleartext = '\0';
                    119:        if (basic->uid) strcpy(cleartext, basic->uid);
                    120:        strcat(cleartext, ":");
                    121:        if (basic->pw) strcat(cleartext, basic->pw);
                    122:        if ((cipher = (char *) HT_MALLOC(ci_len+1)) == NULL)
                    123:            HT_OUTOFMEM("basic_credentials");
                    124:        HTUU_encode((unsigned char *) cleartext, cl_len, cipher);
2.1       luotonen  125: 
2.32      frystyk   126:        /* Create the credentials and assign them to the request object */
                    127:        {
                    128:            int cr_len = strlen("basic") + ci_len + 2;
                    129:            char * cookie = (char *) HT_MALLOC(cr_len+1);
                    130:            if (!cookie) HT_OUTOFMEM("basic_credentials");
                    131:            strcpy(cookie, "Basic ");
                    132:            strcat(cookie, cipher);
2.36    ! frystyk   133:            HTRequest_addCredentials(request, "Authorization", cookie);
2.32      frystyk   134:            HT_FREE(cookie);
2.1       luotonen  135:        }
2.32      frystyk   136:        HT_FREE(cleartext);
                    137:        HT_FREE(cipher);
2.36    ! frystyk   138:        return HT_OK;
2.32      frystyk   139:     }
2.36    ! frystyk   140:     return HT_ERROR;
2.1       luotonen  141: }
                    142: 
2.32      frystyk   143: /*
                    144: **     Prompt the user for username and password.
                    145: **     Returns YES if user name was typed in, else NO
2.1       luotonen  146: */
2.36    ! frystyk   147: PRIVATE int prompt_user (HTRequest * request, const char * realm,
        !           148:                         HTBasic * basic)
2.1       luotonen  149: {
2.32      frystyk   150:     HTAlertCallback * cbf = HTAlert_find(HT_A_USER_PW);
                    151:     if (request && cbf) {
                    152:        HTAlertPar * reply = HTAlert_newReply();        
2.36    ! frystyk   153:        BOOL res = (*cbf)(request, HT_A_USER_PW,HT_MSG_NULL,
        !           154:                          basic->uid, (char *) realm, reply);
2.32      frystyk   155:        if (res) {
2.36    ! frystyk   156:            HT_FREE(basic->uid);
        !           157:            HT_FREE(basic->pw);
        !           158:            basic->uid = HTAlert_replyMessage(reply);
        !           159:            basic->pw = HTAlert_replySecret(reply);
        !           160:            basic->first = NO;
2.32      frystyk   161:        }
                    162:        HTAlert_deleteReply(reply);
2.36    ! frystyk   163:        return res ? HT_OK : HT_ERROR;
2.1       luotonen  164:     }
2.36    ! frystyk   165:     return HT_OK;
2.1       luotonen  166: }
                    167: 
2.32      frystyk   168: /*     HTBasic_generate
                    169: **     ----------------
                    170: **     This function generates "basic" credentials for the challenge found in
                    171: **     the authentication information base for this request. The result is
                    172: **     stored as an association list in the request object.
                    173: **     This is a callback function for the AA handler.
                    174: */
2.36    ! frystyk   175: PUBLIC int HTBasic_generate (HTRequest * request, void * context, int status)
2.32      frystyk   176: { 
2.36    ! frystyk   177:     HTBasic * basic = (HTBasic *) context;
        !           178:     if (request) {
        !           179:        const char * realm = HTRequest_realm(request);
        !           180: 
        !           181:        /* If we don't have a basic context then add a new one to the tree */
        !           182:        if (!basic) {
        !           183:            char * url = HTAnchor_physical(HTRequest_anchor(request));
        !           184:            basic = HTBasic_new();
        !           185:            HTAA_addNode(BASIC_AUTH, realm, url, basic);
        !           186:        }
        !           187: 
2.32      frystyk   188:        /*
2.36    ! frystyk   189:        ** If we have a set of credentials (or the user provides a new set)
        !           190:        ** then store it in the request object as the credentials
2.32      frystyk   191:        */
2.36    ! frystyk   192:        if (basic->uid || prompt_user(request, realm, basic) == HT_OK)
        !           193:            return basic_credentials(request, basic);
2.1       luotonen  194:     }
2.36    ! frystyk   195:     return HT_OK;
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: */
2.36    ! frystyk   206: PUBLIC int HTBasic_parse (HTRequest * request, void * context, int status)
2.32      frystyk   207: {
2.36    ! frystyk   208:     HTAssocList * challenge = HTRequest_challenge(request);
        !           209:     if (request && challenge) {
        !           210:        char * p = HTAssocList_findObject(challenge, BASIC_AUTH);
        !           211:        char * realm = HTNextField(&p);
        !           212:        char * rm = HTNextField(&p);
2.32      frystyk   213:        /*
2.36    ! frystyk   214:        ** If valid challenge then make a template for the resource and
        !           215:        ** store this information in our authentication URL Tree
2.32      frystyk   216:        */
2.36    ! frystyk   217:        if (realm && !strcasecomp(realm, "realm") && rm) {
        !           218:            char * url = HTAnchor_physical(HTRequest_anchor(request));
        !           219:            char * tmplate = make_template(url);
        !           220:            HTBasic * basic = HTBasic_new();
        !           221:            if (AUTH_TRACE) HTTrace("Basic Parse. Realm `%s\' found\n", rm);
        !           222:            HTAA_addNode(BASIC_AUTH, rm, tmplate, basic);
        !           223:            HTRequest_setRealm(request, rm);
        !           224:            HT_FREE(tmplate);
2.1       luotonen  225:        }
2.36    ! frystyk   226:        return HT_OK;
2.1       luotonen  227:     }
2.36    ! frystyk   228:     if (AUTH_TRACE) HTTrace("Auth........ No challenges found\n");
        !           229:     return HT_OK;
2.7       luotonen  230: }
2.1       luotonen  231: 
                    232: 

Webmaster