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

2.15      frystyk     1: /*                                                                  HTAABrow.c
2.1       luotonen    2: **             BROWSER SIDE ACCESS AUTHORIZATION MODULE
2.15      frystyk     3: **
                      4: **     (c) COPYRIGHT CERN 1994.
                      5: **     Please first read the full copyright statement in the file COPYRIGH.
2.1       luotonen    6: **
                      7: **     Containts the code for keeping track on server hostnames,
                      8: **     port numbers, scheme names, usernames, passwords
                      9: **     (and servers' public keys).
                     10: **
                     11: ** IMPORTANT:
                     12: **     Routines in this module use dynamic allocation, but free
                     13: **     automatically all the memory reserved by them.
                     14: **
                     15: **     Therefore the caller never has to (and never should)
                     16: **     free() any object returned by these functions.
                     17: **
                     18: **     Therefore also all the strings returned by this package
                     19: **     are only valid until the next call to the same function
                     20: **     is made. This approach is selected, because of the nature
                     21: **     of access authorization: no string returned by the package
                     22: **     needs to be valid longer than until the next call.
                     23: **
                     24: **     This also makes it easy to plug the AA package in:
                     25: **     you don't have to ponder whether to free() something
                     26: **     here or is it done somewhere else (because it is always
                     27: **     done somewhere else).
                     28: **
                     29: **     The strings that the package needs to store are copied
                     30: **     so the original strings given as parameters to AA
                     31: **     functions may be freed or modified with no side effects.
                     32: **
                     33: **     The AA package does not free() anything else than what
                     34: **     it has itself allocated.
                     35: **
                     36: ** AUTHORS:
                     37: **     AL      Ari Luotonen    luotonen@dxcern.cern.ch
                     38: **
                     39: ** HISTORY:
2.5       luotonen   40: **     Oct 17  AL      Made corrections suggested by marca:
                     41: **                     Added  if (!realm->username) return NULL;
                     42: **                     Changed some ""s to NULLs.
                     43: **                     Now doing calloc() to init uuencode source;
                     44: **                     otherwise HTUU_encode() reads uninitialized memory
                     45: **                     every now and then (not a real bug but not pretty).
                     46: **                     Corrected the formula for uuencode destination size.
2.1       luotonen   47: ** BUGS:
                     48: **
                     49: **
                     50: */
                     51: 
2.16    ! roeber     52: #include "sysdep.h"
2.1       luotonen   53: 
                     54: #include "HTUtils.h"
                     55: #include "HTString.h"
                     56: #include "HTParse.h"           /* URL parsing function         */
                     57: #include "HTList.h"            /* HTList object                */
                     58: #include "HTAlert.h"           /* HTConfirm(), HTPrompt()      */
                     59: #include "HTAAUtil.h"          /* AA common to both sides      */
2.2       luotonen   60: #include "HTAssoc.h"           /* Assoc list                   */
2.1       luotonen   61: #include "HTAABrow.h"          /* Implemented here             */
                     62: #include "HTUU.h"              /* Uuencoding and uudecoding    */
2.7       luotonen   63: #include "HTAccess.h"          /* HTRequest structure          */
2.1       luotonen   64: 
                     65: 
                     66: /*
                     67: ** Module-wide global variables
                     68: */
                     69: 
                     70: PRIVATE HTList *server_table   = NULL; /* Browser's info about servers      */
2.7       luotonen   71: 
2.1       luotonen   72: 
                     73: /**************************** HTAAServer ***********************************/
                     74: 
                     75: 
                     76: /* PRIVATE                                             HTAAServer_new()
                     77: **             ALLOCATE A NEW NODE TO HOLD SERVER INFO
                     78: **             AND ADD IT TO THE LIST OF SERVERS
                     79: ** ON ENTRY:
                     80: **     hostname        is the name of the host that the server
                     81: **                     is running in.
                     82: **     portnumber      is the portnumber which the server listens.
                     83: **
                     84: ** ON EXIT:
                     85: **     returns         the newly-allocated node with all the strings
                     86: **                     duplicated.
                     87: **                     Strings will be automatically freed by
                     88: **                     the function HTAAServer_delete(), which also
                     89: **                     frees the node itself.
                     90: */
                     91: PRIVATE HTAAServer *HTAAServer_new ARGS2(CONST char*,  hostname,
                     92:                                         int,           portnumber)
                     93: {
                     94:     HTAAServer *server;
                     95: 
                     96:     if (!(server = (HTAAServer *)malloc(sizeof(HTAAServer))))
                     97:        outofmem(__FILE__, "HTAAServer_new");
                     98: 
                     99:     server->hostname   = NULL;
                    100:     server->portnumber = (portnumber > 0 ? portnumber : 80);
                    101:     server->setups     = HTList_new();
2.4       luotonen  102:     server->realms     = HTList_new();
2.1       luotonen  103: 
                    104:     if (hostname) StrAllocCopy(server->hostname, hostname);
                    105: 
                    106:     if (!server_table) server_table = HTList_new();
                    107:     
                    108:     HTList_addObject(server_table, (void*)server);
                    109: 
                    110:     return server;
                    111: }
                    112: 
                    113: 
                    114: /* PRIVATE                                             HTAAServer_delete()
                    115: **
                    116: **     DELETE THE ENTRY FOR THE SERVER FROM THE HOST TABLE,
                    117: **     AND FREE THE MEMORY USED BY IT.
                    118: **
                    119: ** ON ENTRY:
                    120: **     killme          points to the HTAAServer to be freed.
                    121: **
                    122: ** ON EXIT:
                    123: **     returns         nothing.
                    124: */
                    125: #ifdef NOT_NEEDED_IT_SEEMS
                    126: PRIVATE void HTAASetup_delete();       /* Forward */
                    127: PRIVATE void HTAAServer_delete ARGS1(HTAAServer *, killme)
                    128: {
                    129:     if (killme) {
2.4       luotonen  130:        HTList *cur1 = killme->setups;
                    131:        HTList *cur2 = killme->realms;
2.1       luotonen  132:        HTAASetup *setup;
2.4       luotonen  133:        HTAARealm *realm;
2.1       luotonen  134: 
2.4       luotonen  135:        while (NULL != (setup = (HTAASetup*)HTList_nextObject(cur1)))
2.1       luotonen  136:            HTAASetup_delete(setup);
                    137:        HTList_delete(killme->setups);
                    138: 
2.4       luotonen  139:        while (NULL != (realm = (HTAARealm*)HTList_nextObject(cur2)))
                    140:            ;   /* This sould free() the realm */
                    141:        HTList_delete(killme->realms);
                    142: 
2.1       luotonen  143:        FREE(killme->hostname);
                    144: 
                    145:        HTList_removeObject(server_table, (void*)killme);
                    146: 
                    147:        free(killme);
                    148:     }
                    149: }
                    150: #endif /*NOT_NEEDED_IT_SEEMS*/
                    151: 
                    152: 
                    153: /* PRIVATE                                             HTAAServer_lookup()
                    154: **             LOOK UP SERVER BY HOSTNAME AND PORTNUMBER
                    155: ** ON ENTRY:
                    156: **     hostname        obvious.
                    157: **     portnumber      if non-positive defaults to 80.
                    158: **
                    159: **     Looks up the server in the module-global server_table.
                    160: **
                    161: ** ON EXIT:
                    162: **     returns         pointer to a HTAAServer structure
                    163: **                     representing the looked-up server.
                    164: **                     NULL, if not found.
                    165: */
                    166: PRIVATE HTAAServer *HTAAServer_lookup ARGS2(CONST char *, hostname,
                    167:                                            int,          portnumber)
                    168: {
                    169:     if (hostname) {
                    170:        HTList *cur = server_table;
                    171:        HTAAServer *server;
                    172: 
                    173:        if (portnumber <= 0) portnumber = 80;
                    174: 
                    175:        while (NULL != (server = (HTAAServer*)HTList_nextObject(cur))) {
                    176:            if (server->portnumber == portnumber  &&
                    177:                0==strcmp(server->hostname, hostname))
                    178:                return server;
                    179:        }
                    180:     }
                    181:     return NULL;       /* NULL parameter, or not found */
                    182: }
                    183: 
                    184: 
                    185: 
                    186: 
                    187: /*************************** HTAASetup *******************************/    
                    188: 
                    189: 
                    190: /* PRIVATE                                             HTAASetup_lookup()
                    191: **     FIGURE OUT WHICH AUTHENTICATION SETUP THE SERVER
                    192: **     IS USING FOR A GIVEN FILE ON A GIVEN HOST AND PORT
                    193: **
                    194: ** ON ENTRY:
                    195: **     hostname        is the name of the server host machine.
                    196: **     portnumber      is the port that the server is running in.
                    197: **     docname         is the (URL-)pathname of the document we
                    198: **                     are trying to access.
                    199: **
                    200: **     This function goes through the information known about
                    201: **     all the setups of the server, and finds out if the given
                    202: **     filename resides in one of the protected directories.
                    203: **
                    204: ** ON EXIT:
                    205: **     returns         NULL if no match.
                    206: **                     Otherwise, a HTAASetup structure representing
                    207: **                     the protected server setup on the corresponding
                    208: **                     document tree.
                    209: **                     
                    210: */
                    211: PRIVATE HTAASetup *HTAASetup_lookup ARGS3(CONST char *, hostname,
                    212:                                          int,          portnumber,
                    213:                                          CONST char *, docname)
                    214: {
                    215:     HTAAServer *server;
                    216:     HTAASetup *setup;
                    217: 
                    218:     if (portnumber <= 0) portnumber = 80;
                    219: 
                    220:     if (hostname && docname && *hostname && *docname &&
                    221:        NULL != (server = HTAAServer_lookup(hostname, portnumber))) {
                    222: 
                    223:        HTList *cur = server->setups;
                    224: 
                    225:        if (TRACE) fprintf(stderr, "%s (%s:%d:%s)\n",
                    226:                           "HTAASetup_lookup: resolving setup for",
                    227:                           hostname, portnumber, docname);
                    228: 
                    229:        while (NULL != (setup = (HTAASetup*)HTList_nextObject(cur))) {
2.13      frystyk   230:            if (HTAA_templateMatch(setup->tmplate, docname)) {
2.1       luotonen  231:                if (TRACE) fprintf(stderr, "%s `%s' %s `%s'\n",
                    232:                                   "HTAASetup_lookup:", docname,
2.13      frystyk   233:                                   "matched template", setup->tmplate);
2.1       luotonen  234:                return setup;
                    235:            }
                    236:            else if (TRACE) fprintf(stderr, "%s `%s' %s `%s'\n",
                    237:                                    "HTAASetup_lookup:", docname,
2.13      frystyk   238:                                    "did NOT match template", setup->tmplate);
2.1       luotonen  239:        } /* while setups remain */
                    240:     } /* if valid parameters and server found */
                    241: 
                    242:     if (TRACE) fprintf(stderr, "%s `%s' %s\n",
                    243:                       "HTAASetup_lookup: No template matched",
                    244:                       (docname ? docname : "(null)"),
                    245:                       "(so probably not protected)");
                    246: 
                    247:     return NULL;       /* NULL in parameters, or not found */
                    248: }
                    249: 
                    250: 
                    251: 
                    252: 
                    253: /* PRIVATE                                             HTAASetup_new()
                    254: **                     CREATE A NEW SETUP NODE
                    255: ** ON ENTRY:
                    256: **     server          is a pointer to a HTAAServer structure
                    257: **                     to which this setup belongs.
                    258: **     template        documents matching this template
                    259: **                     are protected according to this setup.
2.2       luotonen  260: **     valid_schemes   a list containing all valid authentication
                    261: **                     schemes for this setup.
2.1       luotonen  262: **                     If NULL, all schemes are disallowed.
2.2       luotonen  263: **     scheme_specifics is an array of assoc lists, which
                    264: **                     contain scheme specific parameters given
                    265: **                     by server in Authenticate: fields.
2.1       luotonen  266: **                     If NULL, all scheme specifics are
                    267: **                     set to NULL.
                    268: ** ON EXIT:
                    269: **     returns         a new HTAASetup node, and also adds it as
                    270: **                     part of the HTAAServer given as parameter.
                    271: */
                    272: PRIVATE HTAASetup *HTAASetup_new ARGS4(HTAAServer *,   server,
2.13      frystyk   273:                                       char *,          tmplate,
2.2       luotonen  274:                                       HTList *,        valid_schemes,
                    275:                                       HTAssocList **,  scheme_specifics)
2.1       luotonen  276: {
                    277:     HTAASetup *setup;
                    278: 
2.13      frystyk   279:     if (!server || !tmplate || !*tmplate) return NULL;
2.1       luotonen  280: 
                    281:     if (!(setup = (HTAASetup*)malloc(sizeof(HTAASetup))))
                    282:        outofmem(__FILE__, "HTAASetup_new");
                    283: 
2.7       luotonen  284:     setup->reprompt = NO;
2.1       luotonen  285:     setup->server = server;
2.13      frystyk   286:     setup->tmplate = NULL;
                    287:     if (tmplate) StrAllocCopy(setup->tmplate, tmplate);
2.2       luotonen  288:     setup->valid_schemes = valid_schemes;
                    289:     setup->scheme_specifics = scheme_specifics;
2.1       luotonen  290: 
2.2       luotonen  291:     HTList_addObject(server->setups, (void*)setup);
2.1       luotonen  292: 
                    293:     return setup;
                    294: }
                    295: 
                    296: 
                    297: 
                    298: /* PRIVATE                                             HTAASetup_delete()
                    299: **                     FREE A HTAASetup STRUCTURE
                    300: ** ON ENTRY:
                    301: **     killme          is a pointer to the structure to free().
                    302: **
                    303: ** ON EXIT:
                    304: **     returns         nothing.
                    305: */
                    306: #ifdef NOT_NEEDED_IT_SEEMS
                    307: PRIVATE void HTAASetup_delete ARGS1(HTAASetup *, killme)
                    308: {
2.2       luotonen  309:     int scheme;
2.1       luotonen  310: 
                    311:     if (killme) {
2.13      frystyk   312:        if (killme->tmplate) free(killme->tmplate);
2.2       luotonen  313:        if (killme->valid_schemes)
                    314:            HTList_delete(killme->valid_schemes);
                    315:        for (scheme=0; scheme < HTAA_MAX_SCHEMES; scheme++)
                    316:            if (killme->scheme_specifics[scheme])
                    317:                HTAssocList_delete(killme->scheme_specifics[scheme]);
2.1       luotonen  318:        free(killme);
                    319:     }
                    320: }
                    321: #endif /*NOT_NEEDED_IT_SEEMS*/
                    322: 
                    323: 
                    324: 
                    325: /* PRIVATE                                     HTAASetup_updateSpecifics()
                    326: *              COPY SCHEME SPECIFIC PARAMETERS
                    327: **             TO HTAASetup STRUCTURE
                    328: ** ON ENTRY:
                    329: **     setup           destination setup structure.
                    330: **     specifics       string array containing scheme
                    331: **                     specific parameters for each scheme.
                    332: **                     If NULL, all the scheme specific
                    333: **                     parameters are set to NULL.
                    334: **
                    335: ** ON EXIT:
                    336: **     returns         nothing.
                    337: */
2.2       luotonen  338: PRIVATE void HTAASetup_updateSpecifics ARGS2(HTAASetup *,      setup,
                    339:                                             HTAssocList **,    specifics)
2.1       luotonen  340: {
2.2       luotonen  341:     int scheme;
2.1       luotonen  342: 
2.2       luotonen  343:     if (setup) {
                    344:        if (setup->scheme_specifics) {
                    345:            for (scheme=0; scheme < HTAA_MAX_SCHEMES; scheme++) {
                    346:                if (setup->scheme_specifics[scheme])
                    347:                    HTAssocList_delete(setup->scheme_specifics[scheme]);
                    348:            }
                    349:            free(setup->scheme_specifics);
                    350:        }
                    351:        setup->scheme_specifics = specifics;
2.1       luotonen  352:     }
                    353: }
                    354: 
                    355: 
                    356: 
                    357: 
                    358: /*************************** HTAARealm **********************************/
                    359: 
                    360: /* PRIVATE                                             HTAARealm_lookup()
                    361: **             LOOKUP HTAARealm STRUCTURE BY REALM NAME
                    362: ** ON ENTRY:
2.4       luotonen  363: **     realm_table     a list of realm objects.
2.1       luotonen  364: **     realmname       is the name of realm to look for.
                    365: **
                    366: ** ON EXIT:
                    367: **     returns         the realm.  NULL, if not found.
                    368: */
2.4       luotonen  369: PRIVATE HTAARealm *HTAARealm_lookup ARGS2(HTList *,    realm_table,
                    370:                                          CONST char *, realmname)
2.1       luotonen  371: {
                    372:     if (realm_table && realmname) {
                    373:        HTList *cur = realm_table;
                    374:        HTAARealm *realm;
                    375:        
                    376:        while (NULL != (realm = (HTAARealm*)HTList_nextObject(cur))) {
                    377:            if (0==strcmp(realm->realmname, realmname))
                    378:                return realm;
                    379:        }
                    380:     }
                    381:     return NULL;       /* No table, NULL param, or not found */
                    382: }
                    383: 
                    384: 
                    385: 
                    386: /* PRIVATE                                             HTAARealm_new()
                    387: **             CREATE A NODE CONTAINING USERNAME AND
                    388: **             PASSWORD USED FOR THE GIVEN REALM.
                    389: **             IF REALM ALREADY EXISTS, CHANGE
                    390: **             USERNAME/PASSWORD.
                    391: ** ON ENTRY:
2.4       luotonen  392: **     realm_table     a list of realms to where to add
                    393: **                     the new one, too.
2.1       luotonen  394: **     realmname       is the name of the password domain.
                    395: **     username        and
                    396: **     password        are what you can expect them to be.
                    397: **
                    398: ** ON EXIT:
                    399: **     returns         the created realm.
                    400: */
2.4       luotonen  401: PRIVATE HTAARealm *HTAARealm_new ARGS4(HTList *,       realm_table,
                    402:                                       CONST char *,    realmname,
2.1       luotonen  403:                                       CONST char *,    username,
                    404:                                       CONST char *,    password)
                    405: {
                    406:     HTAARealm *realm;
                    407: 
2.4       luotonen  408:     realm = HTAARealm_lookup(realm_table, realmname);
2.1       luotonen  409: 
                    410:     if (!realm) {
                    411:        if (!(realm = (HTAARealm*)malloc(sizeof(HTAARealm))))
                    412:            outofmem(__FILE__, "HTAARealm_new");
                    413:        realm->realmname = NULL;
                    414:        realm->username = NULL;
                    415:        realm->password = NULL;
                    416:        StrAllocCopy(realm->realmname, realmname);
2.4       luotonen  417:        if (realm_table) HTList_addObject(realm_table, (void*)realm);
2.1       luotonen  418:     }
                    419:     if (username) StrAllocCopy(realm->username, username);
                    420:     if (password) StrAllocCopy(realm->password, password);
                    421: 
                    422:     return realm;
                    423: }
                    424: 
                    425: 
                    426: 
                    427: 
                    428: /***************** Basic and Pubkey Authentication ************************/
                    429: 
2.7       luotonen  430: /* PRIVATE                                             compose_Basic_auth()
2.1       luotonen  431: **
2.7       luotonen  432: **             COMPOSE Basic SCHEME AUTHENTICATION STRING
2.1       luotonen  433: **
                    434: ** ON ENTRY:
2.7       luotonen  435: **     req             request, where
                    436: **     req->scheme     == HTAA_BASIC
                    437: **     req->realm      contains username and password.
2.1       luotonen  438: **
                    439: ** ON EXIT:
                    440: **     returns         a newly composed authorization string,
2.5       luotonen  441: **                     NULL, if something fails.
2.1       luotonen  442: ** NOTE:
                    443: **     Like throughout the entire AA package, no string or structure
                    444: **     returned by AA package needs to (or should) be freed.
                    445: **
                    446: */
2.7       luotonen  447: PRIVATE char *compose_Basic_auth ARGS1(HTRequest *, req)
2.1       luotonen  448: {
                    449:     static char *result = NULL;        /* Uuencoded presentation, the result */
                    450:     char *cleartext = NULL;    /* Cleartext presentation */
                    451:     int len;
                    452: 
                    453:     FREE(result);      /* From previous call */
                    454: 
2.7       luotonen  455:     if (!req || req->scheme != HTAA_BASIC || !req->setup ||
                    456:        !req->setup->server)
2.5       luotonen  457:        return NULL;
2.1       luotonen  458: 
2.7       luotonen  459:     if (!req->realm) {
                    460:        char *realmname;
2.1       luotonen  461: 
2.7       luotonen  462:        if (!req->setup || !req->setup->scheme_specifics ||
                    463:            !(realmname =
                    464:              HTAssocList_lookup(req->setup->scheme_specifics[HTAA_BASIC],
                    465:                                 "realm")))
                    466:            return NULL;
                    467: 
                    468:        req->realm = HTAARealm_lookup(req->setup->server->realms, realmname);
                    469:        if (!req->realm) {
                    470:            req->realm = HTAARealm_new(req->setup->server->realms,
                    471:                                       realmname, NULL, NULL);
                    472:            return NULL;
2.1       luotonen  473:        }
                    474:     }
                    475: 
2.7       luotonen  476:     len = strlen(req->realm->username ? req->realm->username : "") +
                    477:          strlen(req->realm->password ? req->realm->password : "") + 3;
2.1       luotonen  478: 
2.5       luotonen  479:     if (!(cleartext  = (char*)calloc(len, 1)))
2.7       luotonen  480:        outofmem(__FILE__, "compose_Basic_auth");
2.1       luotonen  481: 
2.7       luotonen  482:     if (req->realm->username) strcpy(cleartext, req->realm->username);
2.3       luotonen  483:     else *cleartext = (char)0;
2.1       luotonen  484: 
                    485:     strcat(cleartext, ":");
                    486: 
2.7       luotonen  487:     if (req->realm->password) strcat(cleartext, req->realm->password);
                    488: 
                    489:     if (!(result = (char*)malloc(4 * ((len+2)/3) + 1)))
                    490:        outofmem(__FILE__, "compose_Basic_auth");
                    491:     HTUU_encode((unsigned char *)cleartext, strlen(cleartext), result);
                    492:     free(cleartext);
2.1       luotonen  493: 
                    494:     return result;
                    495: }
                    496: 
                    497: 
                    498: 
                    499: /* BROWSER PRIVATE                                     HTAA_selectScheme()
                    500: **             SELECT THE AUTHENTICATION SCHEME TO USE
                    501: ** ON ENTRY:
                    502: **     setup   is the server setup structure which can
                    503: **             be used to make the decision about the
                    504: **             used scheme.
                    505: **
                    506: **     When new authentication methods are added to library
                    507: **     this function makes the decision about which one to
                    508: **     use at a given time.  This can be done by inspecting
                    509: **     environment variables etc.
                    510: **
2.2       luotonen  511: **     Currently only searches for the first valid scheme,
                    512: **     and if nothing found suggests Basic scheme;
                    513: **
2.1       luotonen  514: ** ON EXIT:
                    515: **     returns the authentication scheme to use.
                    516: */
                    517: PRIVATE HTAAScheme HTAA_selectScheme ARGS1(HTAASetup *, setup)
                    518: {
2.14      frystyk   519:     HTAAScheme scheme;
2.2       luotonen  520:     if (setup && setup->valid_schemes) {
2.14      frystyk   521:        for (scheme = HTAA_BASIC; scheme < HTAA_MAX_SCHEMES; scheme++)
2.13      frystyk   522:            if (-1 < HTList_indexOf(setup->valid_schemes, (void *) scheme))
                    523:                return (HTAAScheme) scheme;
2.2       luotonen  524:     }
2.7       luotonen  525:     return HTAA_NONE;
2.1       luotonen  526: }
                    527: 
                    528: 
                    529: 
                    530: 
                    531: /* BROWSER PUBLIC                                      HTAA_composeAuth()
                    532: **
2.7       luotonen  533: **     COMPOSE Authorization: HEADER LINE CONTENTS
2.1       luotonen  534: **     IF WE ALREADY KNOW THAT THE HOST REQUIRES AUTHENTICATION
                    535: **
                    536: ** ON ENTRY:
2.7       luotonen  537: **     req             request, which contains
                    538: **     req->setup      protection setup info on browser.
                    539: **     req->scheme     selected authentication scheme.
                    540: **     req->realm      for Basic scheme the username and password.
                    541: **
                    542: ** ON EXIT:
                    543: **     returns NO, if no authorization seems to be needed, and
                    544: **             req->authorization is NULL.
                    545: **             YES, if it has composed Authorization field,
                    546: **             in which case the result is in req->authorization,
                    547: **             e.g.
                    548: **
                    549: **                "Basic AkRDIhEF8sdEgs72F73bfaS=="
                    550: */
                    551: PUBLIC BOOL HTAA_composeAuth ARGS1(HTRequest *, req)
                    552: {
                    553:     char *auth_string = NULL;
                    554:     static char *docname;
                    555:     static char *hostname;
                    556:     int portnumber;
                    557:     char *colon;
                    558:     char *gate = NULL; /* Obsolite? */
2.9       luotonen  559:     char *arg = NULL;
2.7       luotonen  560: 
                    561:     FREE(hostname);    /* From previous call */
                    562:     FREE(docname);     /*      - " -         */
2.5       luotonen  563: 
2.9       luotonen  564:     if (!req  ||  !req->anchor)
2.7       luotonen  565:        return NO;
2.1       luotonen  566: 
2.10      luotonen  567: #ifdef OLD_CODE
2.8       luotonen  568:     if (req->authorization) {
2.9       luotonen  569:        CTRACE(stderr,
                    570: "HTAA_composeAuth: forwarding auth.info from client\nAuthorization: %s\n",
2.8       luotonen  571:               req->authorization);
                    572:        return YES;
                    573:     }
2.10      luotonen  574: #endif
2.8       luotonen  575: 
2.9       luotonen  576:     arg = HTAnchor_physical(req->anchor);
                    577:     docname = HTParse(arg, "", PARSE_PATH);
                    578:     hostname = HTParse((gate ? gate : arg), "", PARSE_HOST);
2.7       luotonen  579:     if (hostname &&
                    580:        NULL != (colon = strchr(hostname, ':'))) {
                    581:        *(colon++) = '\0';      /* Chop off port number */
                    582:        portnumber = atoi(colon);
                    583:     }
                    584:     else portnumber = 80;
                    585:        
                    586:     if (TRACE) fprintf(stderr,
                    587:                       "Composing Authorization for %s:%d/%s\n",
                    588:                       hostname, portnumber, docname);
2.1       luotonen  589: 
2.7       luotonen  590: #ifdef OLD_CODE
2.1       luotonen  591:     if (current_portnumber != portnumber ||
                    592:        !current_hostname || !current_docname ||
                    593:        !hostname         || !docname         ||
                    594:        0 != strcmp(current_hostname, hostname) ||
                    595:        0 != strcmp(current_docname, docname)) {
                    596: 
                    597:        retry = NO;
                    598: 
                    599:        current_portnumber = portnumber;
                    600:        
                    601:        if (hostname) StrAllocCopy(current_hostname, hostname);
                    602:        else FREE(current_hostname);
                    603: 
                    604:        if (docname) StrAllocCopy(current_docname, docname);
                    605:        else FREE(current_docname);
                    606:     }
                    607:     else retry = YES;
2.7       luotonen  608: #endif /*OLD_CODE*/
2.1       luotonen  609: 
2.7       luotonen  610:     if (!req->setup)
                    611:        req->setup = HTAASetup_lookup(hostname, portnumber, docname);
                    612:     if (!req->setup)
                    613:        return NO;
2.1       luotonen  614: 
2.12      frystyk   615:     if (req->scheme == HTAA_NONE || req->scheme == HTAA_UNKNOWN)
2.7       luotonen  616:        req->scheme = HTAA_selectScheme(req->setup);
2.1       luotonen  617: 
2.7       luotonen  618:     switch (req->scheme) {
2.1       luotonen  619:       case HTAA_BASIC:
2.7       luotonen  620:        auth_string = compose_Basic_auth(req);
                    621:        break;
2.1       luotonen  622:       case HTAA_PUBKEY:
                    623:       case HTAA_KERBEROS_V4:
                    624:        /* OTHER AUTHENTICATION ROUTINES ARE CALLED HERE */
                    625:       default:
                    626:        {
                    627:            char msg[100];
                    628:            sprintf(msg, "%s %s `%s'",
                    629:                    "This client doesn't know how to compose authentication",
2.7       luotonen  630:                    "information for scheme", HTAAScheme_name(req->scheme));
2.1       luotonen  631:            HTAlert(msg);
2.5       luotonen  632:            auth_string = NULL;
2.1       luotonen  633:        }
                    634:     } /* switch scheme */
                    635: 
2.7       luotonen  636:     req->setup->reprompt = NO;
2.1       luotonen  637: 
2.5       luotonen  638:     /* Added by marca. */
                    639:     if (!auth_string)
2.7       luotonen  640:        return NO;
2.5       luotonen  641:     
2.11      frystyk   642:     FREE(req->authorization);   /* Free from previous call, Henrik 14/03-94 */
2.7       luotonen  643:     if (!(req->authorization =
                    644:          (char*)malloc(sizeof(char) * (strlen(auth_string)+40))))
2.1       luotonen  645:        outofmem(__FILE__, "HTAA_composeAuth");
                    646: 
2.7       luotonen  647:     strcpy(req->authorization, HTAAScheme_name(req->scheme));
                    648:     strcat(req->authorization, " ");
                    649:     strcat(req->authorization, auth_string);
2.1       luotonen  650: 
2.7       luotonen  651:     return YES;
                    652: }
2.1       luotonen  653: 
2.5       luotonen  654: 
2.7       luotonen  655: /* BROWSER OVERLOADED                                  HTPasswordDialog()
                    656: **
                    657: **             PROMPT USERNAME AND PASSWORD, AND MAKE A
                    658: **             CALLBACK TO FUNCTION HTLoadHTTP().
2.1       luotonen  659: **
2.7       luotonen  660: **     This function must be redifined by GUI clients, which
                    661: **     call HTLoadHTTP(req) when user presses "Ok".
2.1       luotonen  662: **
2.7       luotonen  663: ** ON ENTRY:
                    664: **     req             request.
                    665: **     req->dialog_msg prompting message.
                    666: **     req->setup      information about protections of this request.
                    667: **     req->realm      structure describing one password realm.
2.1       luotonen  668: **                     This function should only be called when
                    669: **                     server has replied with a 401 (Unauthorized)
2.7       luotonen  670: **                     status code, and req structure has been filled
                    671: **                     up according to server reply, especially the
                    672: **                     req->valid_shemes list must have been set up
                    673: **                     according to WWW-Authenticate: headers.
2.1       luotonen  674: ** ON EXIT:
2.7       luotonen  675: **
2.14      frystyk   676: **     returns YES or NO
2.7       luotonen  677: **
                    678: */
2.14      frystyk   679: PUBLIC int HTPasswordDialog ARGS1(HTRequest *, req)
2.1       luotonen  680: {
2.14      frystyk   681:     if (!req || !req->setup || !req->realm || !req->dialog_msg) {
2.7       luotonen  682:        HTAlert("HTPasswordDialog() called with an illegal parameter");
2.14      frystyk   683:        return NO;
2.7       luotonen  684:     }
                    685:     if (req->setup->reprompt &&
2.14      frystyk   686:        HTConfirm("Authorization failed. Retry?") != YES) {
                    687:        return NO;
                    688:     } else {
2.7       luotonen  689:        char *username = req->realm->username;
                    690:        char *password = NULL;
2.1       luotonen  691: 
2.7       luotonen  692:        HTPromptUsernameAndPassword(req->dialog_msg, &username, &password);
2.1       luotonen  693: 
2.7       luotonen  694:        if (req->realm->username) free(req->realm->username);
                    695:        if (req->realm->password) free(req->realm->password);
                    696:        req->realm->username = username;
                    697:        req->realm->password = password;
2.14      frystyk   698:        if (!req->realm->username)
                    699:            return NO;                        /* Suggested by marca; thanks! */
2.1       luotonen  700: 
2.14      frystyk   701:        return YES;
2.7       luotonen  702:     }
2.14      frystyk   703:     return NO;
2.7       luotonen  704: }
2.1       luotonen  705: 
                    706: 
                    707: 
2.7       luotonen  708: /* BROWSER PUBLIC                                      HTAA_retryWithAuth()
                    709: **
                    710: **             RETRY THE SERVER WITH AUTHORIZATION (OR IF
                    711: **             ALREADY RETRIED, WITH A DIFFERENT USERNAME
                    712: **             AND/OR PASSWORD (IF MISSPELLED)) OR CANCEL
                    713: ** ON ENTRY:
                    714: **     req             request.
                    715: **     req->valid_schemes
                    716: **                     This function should only be called when
                    717: **                     server has replied with a 401 (Unauthorized)
                    718: **                     status code, and req structure has been filled
                    719: **                     up according to server reply, especially the
                    720: **                     req->valid_shemes list must have been set up
                    721: **                     according to WWW-Authenticate: headers.
                    722: ** ON EXIT:
                    723: **     On GUI clients pops up a username/password dialog box
                    724: **     with "Ok" and "Cancel".
                    725: **     "Ok" button press should do a callback
                    726: **
                    727: **             HTLoadHTTP(req);
                    728: **
                    729: **     This actually done by function HTPasswordDialog(),
                    730: **     which GUI clients redefine.
                    731: **
                    732: **     returns         YES, if dialog box was popped up.
                    733: **                     NO, on failure.
                    734: */
2.14      frystyk   735: PUBLIC BOOL HTAA_retryWithAuth ARGS1(HTRequest *,      req)
2.7       luotonen  736: {
                    737:     int len;
                    738:     char *realmname;
2.9       luotonen  739:     char *arg = NULL;
2.1       luotonen  740: 
2.9       luotonen  741:     if (!req || !req->anchor ||
2.7       luotonen  742:        !req->valid_schemes || HTList_count(req->valid_schemes) == 0) {
                    743:        req->setup = NULL;
2.1       luotonen  744:        return NO;
                    745:     }
                    746: 
2.9       luotonen  747:     arg = HTAnchor_physical(req->anchor);
                    748: 
2.7       luotonen  749:     if (req->setup && req->setup->server) {
2.1       luotonen  750:        /* So we have already tried with authorization. */
                    751:        /* Either we don't have access or username or   */
                    752:        /* password was misspelled.                     */
                    753:            
                    754:        /* Update scheme-specific parameters    */
                    755:        /* (in case they have expired by chance).       */
2.7       luotonen  756:        HTAASetup_updateSpecifics(req->setup, req->scheme_specifics);
                    757:        req->scheme = HTAA_selectScheme(req->setup);
                    758:        req->setup->reprompt = YES;
                    759:     }
2.1       luotonen  760:     else { /* current_setup == NULL, i.e. we have a     */
                    761:           /* first connection to a protected server or  */
                    762:           /* the server serves a wider set of documents */
                    763:           /* than we expected so far.                   */
                    764: 
2.7       luotonen  765:        static char *hostname;
                    766:        static char *docname;
                    767:        int portnumber;
                    768:        char *colon;
                    769:        HTAAServer *server;
                    770: 
                    771:        FREE(hostname); /* From previous call */
                    772:        FREE(docname);  /*      - " -         */
                    773: 
2.9       luotonen  774:        docname = HTParse(arg, "", PARSE_PATH);
                    775:        hostname = HTParse(arg, "", PARSE_HOST);
2.7       luotonen  776:        if (hostname &&
                    777:            NULL != (colon = strchr(hostname, ':'))) {
                    778:            *(colon++) = '\0';  /* Chop off port number */
                    779:            portnumber = atoi(colon);
                    780:        }
                    781:        else portnumber = 80;
                    782:        
                    783:        if (TRACE) fprintf(stderr,
                    784:                           "HTAA_retryWithAuth: first retry of %s:%d/%s\n",
                    785:                           hostname, portnumber, docname);
                    786: 
                    787:        if (!(server = HTAAServer_lookup(hostname, portnumber))) {
                    788:            server = HTAAServer_new(hostname, portnumber);
                    789:        }
                    790:        else {
                    791:            HTAlert("Access without authorization denied -- retrying");
2.1       luotonen  792:        }
                    793: 
2.7       luotonen  794:        if (!req->prot_template)
                    795:            req->prot_template = HTAA_makeProtectionTemplate(docname);
                    796:        req->setup = HTAASetup_new(server, 
                    797:                                   req->prot_template,
                    798:                                   req->valid_schemes,
                    799:                                   req->scheme_specifics);
                    800:        req->setup->reprompt = NO;
                    801:        req->scheme = HTAA_selectScheme(req->setup);
                    802: 
2.1       luotonen  803:     } /* else current_setup == NULL */
                    804: 
2.7       luotonen  805:     realmname = HTAssocList_lookup(req->setup->scheme_specifics[req->scheme],
                    806:                                   "realm");
                    807:     if (!realmname)
                    808:        return NO;
                    809: 
                    810:     req->realm = HTAARealm_lookup(req->setup->server->realms, realmname);
                    811:     if (!req->realm)
                    812:        req->realm = HTAARealm_new(req->setup->server->realms,
                    813:                                   realmname, NULL, NULL);
                    814: 
                    815:     len = strlen(realmname) + 100;
                    816:     if (req->setup->server->hostname)
                    817:        len += strlen(req->setup->server->hostname);
2.11      frystyk   818: 
                    819:     FREE(req->dialog_msg);      /* Free from previous call, Henrik 14/03-94 */
2.7       luotonen  820:     if (!(req->dialog_msg = (char*)malloc(len)))
                    821:        outofmem(__FILE__, "HTAA_retryWithAuth");
                    822:     if (!req->realm->username)
                    823:        sprintf(req->dialog_msg, "%s %s at %s",
                    824:                "Document is protected. Enter username for",
                    825:                req->realm->realmname,
                    826:                req->setup->server->hostname
                    827:                ? req->setup->server->hostname : "??");
                    828:     else sprintf(req->dialog_msg, "%s %s at %s",
                    829:                 "Authorization failed. Enter username for",
                    830:                 req->realm->realmname,
                    831:                 req->setup->server->hostname
                    832:                 ? req->setup->server->hostname : "??");
2.14      frystyk   833:     return (HTPasswordDialog(req));
2.11      frystyk   834: }
                    835: 
                    836: 
                    837: /* PUPLIC                                              HTAA_cleanup()
                    838: **
                    839: **     Free the memory used by the entries concerning Access Authorization
                    840: **     in the request structure and put all pointers to NULL
                    841: **     Henrik 14/03-94.
                    842: **
                    843: ** ON ENTRY:
                    844: **     req             the request structure
                    845: **
                    846: ** ON EXIT:
                    847: **     returns         nothing.
                    848: */
                    849: PUBLIC void HTAACleanup ARGS1(HTRequest *, req)
                    850: {
                    851:     if (req) {
                    852:        FREE(req->authorization);
                    853:        FREE(req->prot_template);
                    854:        FREE(req->dialog_msg);
2.12      frystyk   855: #ifdef OLD_CODE 
                    856:        /* Should not be freed as they have become a part of a static
                    857:           memory */
2.11      frystyk   858:        if (req->valid_schemes) {
                    859:            HTList_delete(req->valid_schemes);
                    860:            req->valid_schemes = NULL;
                    861:        }
                    862:        if (req->scheme_specifics) {
                    863:            int cnt;
                    864:            for (cnt=0; cnt<HTAA_MAX_SCHEMES; cnt++) {
                    865:                if (req->scheme_specifics[cnt])
                    866:                    HTAssocList_delete(req->scheme_specifics[cnt]);
                    867:            }
                    868:            FREE(req->scheme_specifics);
                    869:        }
2.12      frystyk   870: #endif /* OLD_CODE */
2.11      frystyk   871:     }
                    872:     return;
2.1       luotonen  873: }
2.7       luotonen  874: 
                    875: 
2.1       luotonen  876: 

Webmaster