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

2.15      frystyk     1: /*                                                                  HTAABrow.c
2.1       luotonen    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: **
                      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.17      frystyk    52: /* Library include files */
                     53: #include "tcp.h"
2.1       luotonen   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: 
2.21      frystyk   225:        if (TRACE)
                    226:            fprintf(TDEST, "Access Auth. resolving setup for (%s:%d:%s)\n",
                    227:                    hostname, portnumber, docname);
2.1       luotonen  228: 
                    229:        while (NULL != (setup = (HTAASetup*)HTList_nextObject(cur))) {
2.13      frystyk   230:            if (HTAA_templateMatch(setup->tmplate, docname)) {
2.21      frystyk   231:                if (TRACE)
                    232:                    fprintf(TDEST, "Access Auth. `%s' matched template `%s'\n",
                    233:                            docname, setup->tmplate);
2.1       luotonen  234:                return setup;
                    235:            }
2.17      frystyk   236:            else if (TRACE) fprintf(TDEST, "%s `%s' %s `%s'\n",
2.1       luotonen  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: 
2.21      frystyk   242:     if (TRACE)
                    243:        fprintf(TDEST, "Access Auth. `%s' (so probably not protected)\n",
                    244:                (docname ? docname : "(null)"));
                    245:     return NULL;                        /* NULL in parameters, or not found */
2.1       luotonen  246: }
                    247: 
                    248: 
                    249: 
                    250: 
                    251: /* PRIVATE                                             HTAASetup_new()
                    252: **                     CREATE A NEW SETUP NODE
                    253: ** ON ENTRY:
                    254: **     server          is a pointer to a HTAAServer structure
                    255: **                     to which this setup belongs.
                    256: **     template        documents matching this template
                    257: **                     are protected according to this setup.
2.2       luotonen  258: **     valid_schemes   a list containing all valid authentication
                    259: **                     schemes for this setup.
2.1       luotonen  260: **                     If NULL, all schemes are disallowed.
2.2       luotonen  261: **     scheme_specifics is an array of assoc lists, which
                    262: **                     contain scheme specific parameters given
                    263: **                     by server in Authenticate: fields.
2.1       luotonen  264: **                     If NULL, all scheme specifics are
                    265: **                     set to NULL.
                    266: ** ON EXIT:
                    267: **     returns         a new HTAASetup node, and also adds it as
                    268: **                     part of the HTAAServer given as parameter.
                    269: */
                    270: PRIVATE HTAASetup *HTAASetup_new ARGS4(HTAAServer *,   server,
2.13      frystyk   271:                                       char *,          tmplate,
2.2       luotonen  272:                                       HTList *,        valid_schemes,
                    273:                                       HTAssocList **,  scheme_specifics)
2.1       luotonen  274: {
                    275:     HTAASetup *setup;
                    276: 
2.13      frystyk   277:     if (!server || !tmplate || !*tmplate) return NULL;
2.1       luotonen  278: 
                    279:     if (!(setup = (HTAASetup*)malloc(sizeof(HTAASetup))))
                    280:        outofmem(__FILE__, "HTAASetup_new");
                    281: 
2.7       luotonen  282:     setup->reprompt = NO;
2.1       luotonen  283:     setup->server = server;
2.13      frystyk   284:     setup->tmplate = NULL;
                    285:     if (tmplate) StrAllocCopy(setup->tmplate, tmplate);
2.2       luotonen  286:     setup->valid_schemes = valid_schemes;
                    287:     setup->scheme_specifics = scheme_specifics;
2.1       luotonen  288: 
2.2       luotonen  289:     HTList_addObject(server->setups, (void*)setup);
2.1       luotonen  290: 
                    291:     return setup;
                    292: }
                    293: 
                    294: 
                    295: 
                    296: /* PRIVATE                                             HTAASetup_delete()
                    297: **                     FREE A HTAASetup STRUCTURE
                    298: ** ON ENTRY:
                    299: **     killme          is a pointer to the structure to free().
                    300: **
                    301: ** ON EXIT:
                    302: **     returns         nothing.
                    303: */
                    304: #ifdef NOT_NEEDED_IT_SEEMS
                    305: PRIVATE void HTAASetup_delete ARGS1(HTAASetup *, killme)
                    306: {
2.2       luotonen  307:     int scheme;
2.1       luotonen  308: 
                    309:     if (killme) {
2.13      frystyk   310:        if (killme->tmplate) free(killme->tmplate);
2.2       luotonen  311:        if (killme->valid_schemes)
                    312:            HTList_delete(killme->valid_schemes);
                    313:        for (scheme=0; scheme < HTAA_MAX_SCHEMES; scheme++)
                    314:            if (killme->scheme_specifics[scheme])
                    315:                HTAssocList_delete(killme->scheme_specifics[scheme]);
2.1       luotonen  316:        free(killme);
                    317:     }
                    318: }
                    319: #endif /*NOT_NEEDED_IT_SEEMS*/
                    320: 
                    321: 
                    322: 
                    323: /* PRIVATE                                     HTAASetup_updateSpecifics()
                    324: *              COPY SCHEME SPECIFIC PARAMETERS
                    325: **             TO HTAASetup STRUCTURE
                    326: ** ON ENTRY:
                    327: **     setup           destination setup structure.
                    328: **     specifics       string array containing scheme
                    329: **                     specific parameters for each scheme.
                    330: **                     If NULL, all the scheme specific
                    331: **                     parameters are set to NULL.
                    332: **
                    333: ** ON EXIT:
                    334: **     returns         nothing.
                    335: */
2.2       luotonen  336: PRIVATE void HTAASetup_updateSpecifics ARGS2(HTAASetup *,      setup,
                    337:                                             HTAssocList **,    specifics)
2.1       luotonen  338: {
2.2       luotonen  339:     int scheme;
2.1       luotonen  340: 
2.2       luotonen  341:     if (setup) {
                    342:        if (setup->scheme_specifics) {
                    343:            for (scheme=0; scheme < HTAA_MAX_SCHEMES; scheme++) {
                    344:                if (setup->scheme_specifics[scheme])
                    345:                    HTAssocList_delete(setup->scheme_specifics[scheme]);
                    346:            }
                    347:            free(setup->scheme_specifics);
                    348:        }
                    349:        setup->scheme_specifics = specifics;
2.1       luotonen  350:     }
                    351: }
                    352: 
                    353: 
                    354: 
                    355: 
                    356: /*************************** HTAARealm **********************************/
                    357: 
                    358: /* PRIVATE                                             HTAARealm_lookup()
                    359: **             LOOKUP HTAARealm STRUCTURE BY REALM NAME
                    360: ** ON ENTRY:
2.4       luotonen  361: **     realm_table     a list of realm objects.
2.1       luotonen  362: **     realmname       is the name of realm to look for.
                    363: **
                    364: ** ON EXIT:
                    365: **     returns         the realm.  NULL, if not found.
                    366: */
2.4       luotonen  367: PRIVATE HTAARealm *HTAARealm_lookup ARGS2(HTList *,    realm_table,
                    368:                                          CONST char *, realmname)
2.1       luotonen  369: {
                    370:     if (realm_table && realmname) {
                    371:        HTList *cur = realm_table;
                    372:        HTAARealm *realm;
                    373:        
                    374:        while (NULL != (realm = (HTAARealm*)HTList_nextObject(cur))) {
                    375:            if (0==strcmp(realm->realmname, realmname))
                    376:                return realm;
                    377:        }
                    378:     }
                    379:     return NULL;       /* No table, NULL param, or not found */
                    380: }
                    381: 
                    382: 
                    383: 
                    384: /* PRIVATE                                             HTAARealm_new()
                    385: **             CREATE A NODE CONTAINING USERNAME AND
                    386: **             PASSWORD USED FOR THE GIVEN REALM.
                    387: **             IF REALM ALREADY EXISTS, CHANGE
                    388: **             USERNAME/PASSWORD.
                    389: ** ON ENTRY:
2.4       luotonen  390: **     realm_table     a list of realms to where to add
                    391: **                     the new one, too.
2.1       luotonen  392: **     realmname       is the name of the password domain.
                    393: **     username        and
                    394: **     password        are what you can expect them to be.
                    395: **
                    396: ** ON EXIT:
                    397: **     returns         the created realm.
                    398: */
2.4       luotonen  399: PRIVATE HTAARealm *HTAARealm_new ARGS4(HTList *,       realm_table,
                    400:                                       CONST char *,    realmname,
2.1       luotonen  401:                                       CONST char *,    username,
                    402:                                       CONST char *,    password)
                    403: {
                    404:     HTAARealm *realm;
                    405: 
2.4       luotonen  406:     realm = HTAARealm_lookup(realm_table, realmname);
2.1       luotonen  407: 
                    408:     if (!realm) {
                    409:        if (!(realm = (HTAARealm*)malloc(sizeof(HTAARealm))))
                    410:            outofmem(__FILE__, "HTAARealm_new");
                    411:        realm->realmname = NULL;
                    412:        realm->username = NULL;
                    413:        realm->password = NULL;
                    414:        StrAllocCopy(realm->realmname, realmname);
2.4       luotonen  415:        if (realm_table) HTList_addObject(realm_table, (void*)realm);
2.1       luotonen  416:     }
                    417:     if (username) StrAllocCopy(realm->username, username);
                    418:     if (password) StrAllocCopy(realm->password, password);
                    419: 
                    420:     return realm;
                    421: }
                    422: 
                    423: 
                    424: 
                    425: 
                    426: /***************** Basic and Pubkey Authentication ************************/
                    427: 
2.7       luotonen  428: /* PRIVATE                                             compose_Basic_auth()
2.1       luotonen  429: **
2.7       luotonen  430: **             COMPOSE Basic SCHEME AUTHENTICATION STRING
2.1       luotonen  431: **
                    432: ** ON ENTRY:
2.7       luotonen  433: **     req             request, where
                    434: **     req->scheme     == HTAA_BASIC
                    435: **     req->realm      contains username and password.
2.1       luotonen  436: **
                    437: ** ON EXIT:
                    438: **     returns         a newly composed authorization string,
2.5       luotonen  439: **                     NULL, if something fails.
2.1       luotonen  440: ** NOTE:
                    441: **     Like throughout the entire AA package, no string or structure
                    442: **     returned by AA package needs to (or should) be freed.
                    443: **
                    444: */
2.7       luotonen  445: PRIVATE char *compose_Basic_auth ARGS1(HTRequest *, req)
2.1       luotonen  446: {
                    447:     static char *result = NULL;        /* Uuencoded presentation, the result */
                    448:     char *cleartext = NULL;    /* Cleartext presentation */
                    449:     int len;
                    450: 
                    451:     FREE(result);      /* From previous call */
                    452: 
2.7       luotonen  453:     if (!req || req->scheme != HTAA_BASIC || !req->setup ||
                    454:        !req->setup->server)
2.5       luotonen  455:        return NULL;
2.1       luotonen  456: 
2.7       luotonen  457:     if (!req->realm) {
                    458:        char *realmname;
2.1       luotonen  459: 
2.7       luotonen  460:        if (!req->setup || !req->setup->scheme_specifics ||
                    461:            !(realmname =
                    462:              HTAssocList_lookup(req->setup->scheme_specifics[HTAA_BASIC],
                    463:                                 "realm")))
                    464:            return NULL;
                    465: 
                    466:        req->realm = HTAARealm_lookup(req->setup->server->realms, realmname);
                    467:        if (!req->realm) {
                    468:            req->realm = HTAARealm_new(req->setup->server->realms,
                    469:                                       realmname, NULL, NULL);
                    470:            return NULL;
2.1       luotonen  471:        }
                    472:     }
                    473: 
2.7       luotonen  474:     len = strlen(req->realm->username ? req->realm->username : "") +
                    475:          strlen(req->realm->password ? req->realm->password : "") + 3;
2.1       luotonen  476: 
2.5       luotonen  477:     if (!(cleartext  = (char*)calloc(len, 1)))
2.7       luotonen  478:        outofmem(__FILE__, "compose_Basic_auth");
2.1       luotonen  479: 
2.7       luotonen  480:     if (req->realm->username) strcpy(cleartext, req->realm->username);
2.3       luotonen  481:     else *cleartext = (char)0;
2.1       luotonen  482: 
                    483:     strcat(cleartext, ":");
                    484: 
2.7       luotonen  485:     if (req->realm->password) strcat(cleartext, req->realm->password);
                    486: 
                    487:     if (!(result = (char*)malloc(4 * ((len+2)/3) + 1)))
                    488:        outofmem(__FILE__, "compose_Basic_auth");
                    489:     HTUU_encode((unsigned char *)cleartext, strlen(cleartext), result);
                    490:     free(cleartext);
2.1       luotonen  491: 
                    492:     return result;
                    493: }
                    494: 
                    495: 
                    496: 
                    497: /* BROWSER PRIVATE                                     HTAA_selectScheme()
                    498: **             SELECT THE AUTHENTICATION SCHEME TO USE
                    499: ** ON ENTRY:
                    500: **     setup   is the server setup structure which can
                    501: **             be used to make the decision about the
                    502: **             used scheme.
                    503: **
                    504: **     When new authentication methods are added to library
                    505: **     this function makes the decision about which one to
                    506: **     use at a given time.  This can be done by inspecting
                    507: **     environment variables etc.
                    508: **
2.2       luotonen  509: **     Currently only searches for the first valid scheme,
                    510: **     and if nothing found suggests Basic scheme;
                    511: **
2.1       luotonen  512: ** ON EXIT:
                    513: **     returns the authentication scheme to use.
                    514: */
                    515: PRIVATE HTAAScheme HTAA_selectScheme ARGS1(HTAASetup *, setup)
                    516: {
2.14      frystyk   517:     HTAAScheme scheme;
2.2       luotonen  518:     if (setup && setup->valid_schemes) {
2.14      frystyk   519:        for (scheme = HTAA_BASIC; scheme < HTAA_MAX_SCHEMES; scheme++)
2.13      frystyk   520:            if (-1 < HTList_indexOf(setup->valid_schemes, (void *) scheme))
                    521:                return (HTAAScheme) scheme;
2.2       luotonen  522:     }
2.7       luotonen  523:     return HTAA_NONE;
2.1       luotonen  524: }
                    525: 
                    526: 
                    527: 
                    528: 
                    529: /* BROWSER PUBLIC                                      HTAA_composeAuth()
                    530: **
2.7       luotonen  531: **     COMPOSE Authorization: HEADER LINE CONTENTS
2.1       luotonen  532: **     IF WE ALREADY KNOW THAT THE HOST REQUIRES AUTHENTICATION
                    533: **
                    534: ** ON ENTRY:
2.7       luotonen  535: **     req             request, which contains
                    536: **     req->setup      protection setup info on browser.
                    537: **     req->scheme     selected authentication scheme.
                    538: **     req->realm      for Basic scheme the username and password.
                    539: **
                    540: ** ON EXIT:
                    541: **     returns NO, if no authorization seems to be needed, and
                    542: **             req->authorization is NULL.
                    543: **             YES, if it has composed Authorization field,
                    544: **             in which case the result is in req->authorization,
                    545: **             e.g.
                    546: **
                    547: **                "Basic AkRDIhEF8sdEgs72F73bfaS=="
                    548: */
                    549: PUBLIC BOOL HTAA_composeAuth ARGS1(HTRequest *, req)
                    550: {
                    551:     char *auth_string = NULL;
                    552:     static char *docname;
                    553:     static char *hostname;
                    554:     int portnumber;
                    555:     char *colon;
                    556:     char *gate = NULL; /* Obsolite? */
2.9       luotonen  557:     char *arg = NULL;
2.7       luotonen  558: 
                    559:     FREE(hostname);    /* From previous call */
                    560:     FREE(docname);     /*      - " -         */
2.5       luotonen  561: 
2.9       luotonen  562:     if (!req  ||  !req->anchor)
2.7       luotonen  563:        return NO;
2.1       luotonen  564: 
2.9       luotonen  565:     arg = HTAnchor_physical(req->anchor);
                    566:     docname = HTParse(arg, "", PARSE_PATH);
                    567:     hostname = HTParse((gate ? gate : arg), "", PARSE_HOST);
2.7       luotonen  568:     if (hostname &&
                    569:        NULL != (colon = strchr(hostname, ':'))) {
                    570:        *(colon++) = '\0';      /* Chop off port number */
                    571:        portnumber = atoi(colon);
                    572:     }
                    573:     else portnumber = 80;
                    574:        
2.21      frystyk   575:     if (TRACE)
                    576:        fprintf(TDEST, "Access Auth. composing authorization for %s:%d/%s\n",
                    577:                hostname, portnumber, docname);
2.1       luotonen  578: 
2.7       luotonen  579: #ifdef OLD_CODE
2.1       luotonen  580:     if (current_portnumber != portnumber ||
                    581:        !current_hostname || !current_docname ||
                    582:        !hostname         || !docname         ||
                    583:        0 != strcmp(current_hostname, hostname) ||
                    584:        0 != strcmp(current_docname, docname)) {
                    585: 
                    586:        retry = NO;
                    587: 
                    588:        current_portnumber = portnumber;
                    589:        
                    590:        if (hostname) StrAllocCopy(current_hostname, hostname);
                    591:        else FREE(current_hostname);
                    592: 
                    593:        if (docname) StrAllocCopy(current_docname, docname);
                    594:        else FREE(current_docname);
                    595:     }
                    596:     else retry = YES;
2.7       luotonen  597: #endif /*OLD_CODE*/
2.1       luotonen  598: 
2.7       luotonen  599:     if (!req->setup)
                    600:        req->setup = HTAASetup_lookup(hostname, portnumber, docname);
                    601:     if (!req->setup)
                    602:        return NO;
2.1       luotonen  603: 
2.12      frystyk   604:     if (req->scheme == HTAA_NONE || req->scheme == HTAA_UNKNOWN)
2.7       luotonen  605:        req->scheme = HTAA_selectScheme(req->setup);
2.1       luotonen  606: 
2.7       luotonen  607:     switch (req->scheme) {
2.1       luotonen  608:       case HTAA_BASIC:
2.7       luotonen  609:        auth_string = compose_Basic_auth(req);
                    610:        break;
2.1       luotonen  611:       case HTAA_PUBKEY:
                    612:       case HTAA_KERBEROS_V4:
                    613:        /* OTHER AUTHENTICATION ROUTINES ARE CALLED HERE */
                    614:       default:
                    615:        {
                    616:            char msg[100];
                    617:            sprintf(msg, "%s %s `%s'",
                    618:                    "This client doesn't know how to compose authentication",
2.7       luotonen  619:                    "information for scheme", HTAAScheme_name(req->scheme));
2.22    ! frystyk   620:            HTAlert(req, msg);
2.5       luotonen  621:            auth_string = NULL;
2.1       luotonen  622:        }
                    623:     } /* switch scheme */
                    624: 
2.7       luotonen  625:     req->setup->reprompt = NO;
2.1       luotonen  626: 
2.5       luotonen  627:     /* Added by marca. */
                    628:     if (!auth_string)
2.7       luotonen  629:        return NO;
2.5       luotonen  630:     
2.11      frystyk   631:     FREE(req->authorization);   /* Free from previous call, Henrik 14/03-94 */
2.7       luotonen  632:     if (!(req->authorization =
                    633:          (char*)malloc(sizeof(char) * (strlen(auth_string)+40))))
2.1       luotonen  634:        outofmem(__FILE__, "HTAA_composeAuth");
                    635: 
2.7       luotonen  636:     strcpy(req->authorization, HTAAScheme_name(req->scheme));
                    637:     strcat(req->authorization, " ");
                    638:     strcat(req->authorization, auth_string);
2.1       luotonen  639: 
2.7       luotonen  640:     return YES;
                    641: }
2.1       luotonen  642: 
2.5       luotonen  643: 
2.7       luotonen  644: /* BROWSER OVERLOADED                                  HTPasswordDialog()
                    645: **
                    646: **             PROMPT USERNAME AND PASSWORD, AND MAKE A
                    647: **             CALLBACK TO FUNCTION HTLoadHTTP().
2.1       luotonen  648: **
2.7       luotonen  649: **     This function must be redifined by GUI clients, which
                    650: **     call HTLoadHTTP(req) when user presses "Ok".
2.1       luotonen  651: **
2.7       luotonen  652: ** ON ENTRY:
                    653: **     req             request.
                    654: **     req->dialog_msg prompting message.
                    655: **     req->setup      information about protections of this request.
                    656: **     req->realm      structure describing one password realm.
2.1       luotonen  657: **                     This function should only be called when
                    658: **                     server has replied with a 401 (Unauthorized)
2.7       luotonen  659: **                     status code, and req structure has been filled
                    660: **                     up according to server reply, especially the
                    661: **                     req->valid_shemes list must have been set up
                    662: **                     according to WWW-Authenticate: headers.
2.1       luotonen  663: ** ON EXIT:
2.7       luotonen  664: **
2.14      frystyk   665: **     returns YES or NO
2.7       luotonen  666: **
                    667: */
2.18      frystyk   668: PUBLIC BOOL HTPasswordDialog ARGS1(HTRequest *,        req)
2.1       luotonen  669: {
2.14      frystyk   670:     if (!req || !req->setup || !req->realm || !req->dialog_msg) {
2.22    ! frystyk   671:        if (PROT_TRACE)
        !           672:            fprintf(TDEST, "Access...... called with an illegal parameter");
2.14      frystyk   673:        return NO;
2.7       luotonen  674:     }
                    675:     if (req->setup->reprompt &&
2.22    ! frystyk   676:        HTConfirm(req, "Authorization failed. Retry?") != YES) {
2.14      frystyk   677:        return NO;
                    678:     } else {
2.7       luotonen  679:        char *username = req->realm->username;
                    680:        char *password = NULL;
2.1       luotonen  681: 
2.22    ! frystyk   682:        HTPromptUsernameAndPassword(req,req->dialog_msg, &username, &password);
2.1       luotonen  683: 
2.7       luotonen  684:        if (req->realm->username) free(req->realm->username);
                    685:        if (req->realm->password) free(req->realm->password);
                    686:        req->realm->username = username;
                    687:        req->realm->password = password;
2.14      frystyk   688:        if (!req->realm->username)
                    689:            return NO;                        /* Suggested by marca; thanks! */
2.1       luotonen  690: 
2.14      frystyk   691:        return YES;
2.7       luotonen  692:     }
2.14      frystyk   693:     return NO;
2.7       luotonen  694: }
2.1       luotonen  695: 
                    696: 
                    697: 
2.7       luotonen  698: /* BROWSER PUBLIC                                      HTAA_retryWithAuth()
                    699: **
                    700: **             RETRY THE SERVER WITH AUTHORIZATION (OR IF
                    701: **             ALREADY RETRIED, WITH A DIFFERENT USERNAME
                    702: **             AND/OR PASSWORD (IF MISSPELLED)) OR CANCEL
                    703: ** ON ENTRY:
                    704: **     req             request.
                    705: **     req->valid_schemes
                    706: **                     This function should only be called when
                    707: **                     server has replied with a 401 (Unauthorized)
                    708: **                     status code, and req structure has been filled
                    709: **                     up according to server reply, especially the
                    710: **                     req->valid_shemes list must have been set up
                    711: **                     according to WWW-Authenticate: headers.
                    712: ** ON EXIT:
                    713: **     On GUI clients pops up a username/password dialog box
                    714: **     with "Ok" and "Cancel".
                    715: **     "Ok" button press should do a callback
                    716: **
                    717: **             HTLoadHTTP(req);
                    718: **
                    719: **     This actually done by function HTPasswordDialog(),
                    720: **     which GUI clients redefine.
                    721: **
                    722: **     returns         YES, if dialog box was popped up.
                    723: **                     NO, on failure.
                    724: */
2.14      frystyk   725: PUBLIC BOOL HTAA_retryWithAuth ARGS1(HTRequest *,      req)
2.7       luotonen  726: {
                    727:     int len;
                    728:     char *realmname;
2.9       luotonen  729:     char *arg = NULL;
2.1       luotonen  730: 
2.9       luotonen  731:     if (!req || !req->anchor ||
2.7       luotonen  732:        !req->valid_schemes || HTList_count(req->valid_schemes) == 0) {
                    733:        req->setup = NULL;
2.1       luotonen  734:        return NO;
                    735:     }
                    736: 
2.9       luotonen  737:     arg = HTAnchor_physical(req->anchor);
                    738: 
2.7       luotonen  739:     if (req->setup && req->setup->server) {
2.1       luotonen  740:        /* So we have already tried with authorization. */
                    741:        /* Either we don't have access or username or   */
                    742:        /* password was misspelled.                     */
                    743:            
                    744:        /* Update scheme-specific parameters    */
                    745:        /* (in case they have expired by chance).       */
2.7       luotonen  746:        HTAASetup_updateSpecifics(req->setup, req->scheme_specifics);
                    747:        req->scheme = HTAA_selectScheme(req->setup);
                    748:        req->setup->reprompt = YES;
                    749:     }
2.1       luotonen  750:     else { /* current_setup == NULL, i.e. we have a     */
                    751:           /* first connection to a protected server or  */
                    752:           /* the server serves a wider set of documents */
                    753:           /* than we expected so far.                   */
                    754: 
2.7       luotonen  755:        static char *hostname;
                    756:        static char *docname;
                    757:        int portnumber;
                    758:        char *colon;
                    759:        HTAAServer *server;
                    760: 
                    761:        FREE(hostname); /* From previous call */
                    762:        FREE(docname);  /*      - " -         */
                    763: 
2.9       luotonen  764:        docname = HTParse(arg, "", PARSE_PATH);
                    765:        hostname = HTParse(arg, "", PARSE_HOST);
2.7       luotonen  766:        if (hostname &&
                    767:            NULL != (colon = strchr(hostname, ':'))) {
                    768:            *(colon++) = '\0';  /* Chop off port number */
                    769:            portnumber = atoi(colon);
                    770:        }
                    771:        else portnumber = 80;
                    772:        
2.17      frystyk   773:        if (TRACE) fprintf(TDEST,
2.7       luotonen  774:                           "HTAA_retryWithAuth: first retry of %s:%d/%s\n",
                    775:                           hostname, portnumber, docname);
                    776: 
                    777:        if (!(server = HTAAServer_lookup(hostname, portnumber))) {
                    778:            server = HTAAServer_new(hostname, portnumber);
                    779:        }
                    780:        else {
2.22    ! frystyk   781:            HTAlert(req, "Access without authorization denied -- retrying");
2.1       luotonen  782:        }
                    783: 
2.7       luotonen  784:        if (!req->prot_template)
                    785:            req->prot_template = HTAA_makeProtectionTemplate(docname);
                    786:        req->setup = HTAASetup_new(server, 
                    787:                                   req->prot_template,
                    788:                                   req->valid_schemes,
                    789:                                   req->scheme_specifics);
                    790:        req->setup->reprompt = NO;
                    791:        req->scheme = HTAA_selectScheme(req->setup);
                    792: 
2.1       luotonen  793:     } /* else current_setup == NULL */
                    794: 
2.7       luotonen  795:     realmname = HTAssocList_lookup(req->setup->scheme_specifics[req->scheme],
                    796:                                   "realm");
                    797:     if (!realmname)
                    798:        return NO;
                    799: 
                    800:     req->realm = HTAARealm_lookup(req->setup->server->realms, realmname);
                    801:     if (!req->realm)
                    802:        req->realm = HTAARealm_new(req->setup->server->realms,
                    803:                                   realmname, NULL, NULL);
                    804: 
                    805:     len = strlen(realmname) + 100;
                    806:     if (req->setup->server->hostname)
                    807:        len += strlen(req->setup->server->hostname);
2.11      frystyk   808: 
                    809:     FREE(req->dialog_msg);      /* Free from previous call, Henrik 14/03-94 */
2.7       luotonen  810:     if (!(req->dialog_msg = (char*)malloc(len)))
                    811:        outofmem(__FILE__, "HTAA_retryWithAuth");
                    812:     if (!req->realm->username)
2.20      frystyk   813:        sprintf(req->dialog_msg, "\n%s %s at %s",
2.7       luotonen  814:                "Document is protected. Enter username for",
                    815:                req->realm->realmname,
                    816:                req->setup->server->hostname
                    817:                ? req->setup->server->hostname : "??");
2.20      frystyk   818:     else sprintf(req->dialog_msg, "\n%s %s at %s",
2.7       luotonen  819:                 "Authorization failed. Enter username for",
                    820:                 req->realm->realmname,
                    821:                 req->setup->server->hostname
                    822:                 ? req->setup->server->hostname : "??");
2.14      frystyk   823:     return (HTPasswordDialog(req));
2.11      frystyk   824: }
                    825: 
                    826: 
                    827: /* PUPLIC                                              HTAA_cleanup()
                    828: **
                    829: **     Free the memory used by the entries concerning Access Authorization
                    830: **     in the request structure and put all pointers to NULL
                    831: **     Henrik 14/03-94.
                    832: **
                    833: ** ON ENTRY:
                    834: **     req             the request structure
                    835: **
                    836: ** ON EXIT:
                    837: **     returns         nothing.
                    838: */
                    839: PUBLIC void HTAACleanup ARGS1(HTRequest *, req)
                    840: {
                    841:     if (req) {
                    842:        FREE(req->authorization);
                    843:        FREE(req->prot_template);
                    844:        FREE(req->dialog_msg);
2.12      frystyk   845: #ifdef OLD_CODE 
                    846:        /* Should not be freed as they have become a part of a static
                    847:           memory */
2.11      frystyk   848:        if (req->valid_schemes) {
                    849:            HTList_delete(req->valid_schemes);
                    850:            req->valid_schemes = NULL;
                    851:        }
                    852:        if (req->scheme_specifics) {
                    853:            int cnt;
                    854:            for (cnt=0; cnt<HTAA_MAX_SCHEMES; cnt++) {
                    855:                if (req->scheme_specifics[cnt])
                    856:                    HTAssocList_delete(req->scheme_specifics[cnt]);
                    857:            }
                    858:            FREE(req->scheme_specifics);
                    859:        }
2.12      frystyk   860: #endif /* OLD_CODE */
2.11      frystyk   861:     }
                    862:     return;
2.1       luotonen  863: }
2.7       luotonen  864: 
                    865: 
2.1       luotonen  866: 

Webmaster