Annotation of libwww/Library/src/HTAABrow.c, revision 2.36
2.15 frystyk 1: /* HTAABrow.c
2.32 frystyk 2: ** BROWSER SIDE ACCESS AUTHORIZATION MODULE
2.15 frystyk 3: **
2.19 frystyk 4: ** (c) COPYRIGHT MIT 1995.
2.15 frystyk 5: ** Please first read the full copyright statement in the file COPYRIGH.
2.36 ! frystyk 6: ** @(#) $Id: HTAABrow.c,v 2.35 1996/07/02 22:54:07 frystyk Exp $
2.1 luotonen 7: **
2.32 frystyk 8: ** Contains code for parsing challenges and creating credentials for
2.36 ! frystyk 9: ** basic authentication schemes. See also the HTAAUtil module
2.32 frystyk 10: ** for how to handle other authentication schemes. You don't have to use
11: ** this code at all.
2.1 luotonen 12: **
13: ** AUTHORS:
14: ** AL Ari Luotonen luotonen@dxcern.cern.ch
2.32 frystyk 15: ** HFN Henrik Frystyk
2.1 luotonen 16: **
17: ** HISTORY:
2.5 luotonen 18: ** Oct 17 AL Made corrections suggested by marca:
19: ** Added if (!realm->username) return NULL;
20: ** Changed some ""s to NULLs.
2.33 frystyk 21: ** Now doing HT_CALLOC() to init uuencode source;
2.5 luotonen 22: ** otherwise HTUU_encode() reads uninitialized memory
23: ** every now and then (not a real bug but not pretty).
24: ** Corrected the formula for uuencode destination size.
2.32 frystyk 25: ** Feb 96 HFN Rewritten to make it scheme independent and based on
26: ** callback functions and an info structure
2.1 luotonen 27: */
28:
2.17 frystyk 29: /* Library include files */
2.27 frystyk 30: #include "WWWLib.h"
31: #include "HTAAUtil.h"
32: #include "HTAABrow.h" /* Implemented here */
2.1 luotonen 33:
2.36 ! frystyk 34: #define BASIC_AUTH "basic"
! 35:
2.32 frystyk 36: typedef struct _HTBasic { /* Basic challenge and credentials */
37: char * uid;
38: char * pw;
2.36 ! frystyk 39: BOOL first;
2.32 frystyk 40: } HTBasic;
41:
2.36 ! frystyk 42: /* ------------------------------------------------------------------------- */
! 43:
! 44: PRIVATE HTBasic * HTBasic_new()
! 45: {
! 46: HTBasic * me = NULL;
! 47: if ((me = (HTBasic *) HT_CALLOC(1, sizeof(HTBasic))) == NULL)
! 48: HT_OUTOFMEM("HTBasic_new");
! 49: me->first = YES;
! 50: return me;
! 51: }
2.7 luotonen 52:
2.36 ! frystyk 53: /* HTBasic_delete
! 54: ** --------------
! 55: ** Deletes a "basic" information object
! 56: */
! 57: PUBLIC int HTBasic_delete (void * context)
! 58: {
! 59: HTBasic * basic = (HTBasic *) context;
! 60: if (basic) {
! 61: HT_FREE(basic->uid);
! 62: HT_FREE(basic->pw);
! 63: HT_FREE(basic);
! 64: return YES;
! 65: }
! 66: return NO;
! 67: }
2.1 luotonen 68:
2.32 frystyk 69: /*
70: ** Create a protection template for the files
71: ** in the same directory as the given file
72: ** Returns a template matching docname, and other files in that directory.
73: **
74: ** E.g. /foo/bar/x.html => /foo/bar/ *
75: ** ^
76: ** Space only to prevent it from
77: ** being a comment marker here,
78: ** there really isn't any space.
2.1 luotonen 79: */
2.33 frystyk 80: PRIVATE char * make_template (const char * docname)
2.1 luotonen 81: {
2.32 frystyk 82: char *tmplate = NULL;
83: char *slash = NULL;
84: if (docname) {
85: StrAllocCopy(tmplate, docname);
86: slash = strrchr(tmplate, '/');
87: if (slash) slash++;
88: else slash = tmplate;
89: *slash = '\0';
90: StrAllocCat(tmplate, "*");
91: }
92: else StrAllocCopy(tmplate, "*");
93: if (AUTH_TRACE)
94: HTTrace("Template.... Made template `%s' for file `%s'\n",
95: tmplate, docname);
96: return tmplate;
2.1 luotonen 97: }
98:
2.32 frystyk 99: /*
100: ** Make basic authentication scheme credentials and register this
101: ** information in the request object as credentials. They will then
102: ** be included in the request header. An example is
103: **
104: ** "Basic AkRDIhEF8sdEgs72F73bfaS=="
105: **
2.36 ! frystyk 106: ** Returns HT_OK or HT_ERROR
2.32 frystyk 107: */
2.36 ! frystyk 108: PRIVATE BOOL basic_credentials (HTRequest * request, HTBasic * basic)
2.32 frystyk 109: {
110: if (request && basic) {
111: char * cleartext = NULL;
112: char * cipher = NULL;
113: int cl_len = strlen(basic->uid ? basic->uid : "") +
114: strlen(basic->pw ? basic->pw : "") + 3;
115: int ci_len = (4*(cl_len+2))/3;
116: if ((cleartext = (char *) HT_CALLOC(1, cl_len+3)) == NULL)
117: HT_OUTOFMEM("basic_credentials");
118: *cleartext = '\0';
119: if (basic->uid) strcpy(cleartext, basic->uid);
120: strcat(cleartext, ":");
121: if (basic->pw) strcat(cleartext, basic->pw);
122: if ((cipher = (char *) HT_MALLOC(ci_len+1)) == NULL)
123: HT_OUTOFMEM("basic_credentials");
124: HTUU_encode((unsigned char *) cleartext, cl_len, cipher);
2.1 luotonen 125:
2.32 frystyk 126: /* Create the credentials and assign them to the request object */
127: {
128: int cr_len = strlen("basic") + ci_len + 2;
129: char * cookie = (char *) HT_MALLOC(cr_len+1);
130: if (!cookie) HT_OUTOFMEM("basic_credentials");
131: strcpy(cookie, "Basic ");
132: strcat(cookie, cipher);
2.36 ! frystyk 133: HTRequest_addCredentials(request, "Authorization", cookie);
2.32 frystyk 134: HT_FREE(cookie);
2.1 luotonen 135: }
2.32 frystyk 136: HT_FREE(cleartext);
137: HT_FREE(cipher);
2.36 ! frystyk 138: return HT_OK;
2.32 frystyk 139: }
2.36 ! frystyk 140: return HT_ERROR;
2.1 luotonen 141: }
142:
2.32 frystyk 143: /*
144: ** Prompt the user for username and password.
145: ** Returns YES if user name was typed in, else NO
2.1 luotonen 146: */
2.36 ! frystyk 147: PRIVATE int prompt_user (HTRequest * request, const char * realm,
! 148: HTBasic * basic)
2.1 luotonen 149: {
2.32 frystyk 150: HTAlertCallback * cbf = HTAlert_find(HT_A_USER_PW);
151: if (request && cbf) {
152: HTAlertPar * reply = HTAlert_newReply();
2.36 ! frystyk 153: BOOL res = (*cbf)(request, HT_A_USER_PW,HT_MSG_NULL,
! 154: basic->uid, (char *) realm, reply);
2.32 frystyk 155: if (res) {
2.36 ! frystyk 156: HT_FREE(basic->uid);
! 157: HT_FREE(basic->pw);
! 158: basic->uid = HTAlert_replyMessage(reply);
! 159: basic->pw = HTAlert_replySecret(reply);
! 160: basic->first = NO;
2.32 frystyk 161: }
162: HTAlert_deleteReply(reply);
2.36 ! frystyk 163: return res ? HT_OK : HT_ERROR;
2.1 luotonen 164: }
2.36 ! frystyk 165: return HT_OK;
2.1 luotonen 166: }
167:
2.32 frystyk 168: /* HTBasic_generate
169: ** ----------------
170: ** This function generates "basic" credentials for the challenge found in
171: ** the authentication information base for this request. The result is
172: ** stored as an association list in the request object.
173: ** This is a callback function for the AA handler.
174: */
2.36 ! frystyk 175: PUBLIC int HTBasic_generate (HTRequest * request, void * context, int status)
2.32 frystyk 176: {
2.36 ! frystyk 177: HTBasic * basic = (HTBasic *) context;
! 178: if (request) {
! 179: const char * realm = HTRequest_realm(request);
! 180:
! 181: /* If we don't have a basic context then add a new one to the tree */
! 182: if (!basic) {
! 183: char * url = HTAnchor_physical(HTRequest_anchor(request));
! 184: basic = HTBasic_new();
! 185: HTAA_addNode(BASIC_AUTH, realm, url, basic);
! 186: }
! 187:
2.32 frystyk 188: /*
2.36 ! frystyk 189: ** If we have a set of credentials (or the user provides a new set)
! 190: ** then store it in the request object as the credentials
2.32 frystyk 191: */
2.36 ! frystyk 192: if (basic->uid || prompt_user(request, realm, basic) == HT_OK)
! 193: return basic_credentials(request, basic);
2.1 luotonen 194: }
2.36 ! frystyk 195: return HT_OK;
2.1 luotonen 196: }
197:
2.32 frystyk 198: /* HTBasic_parse
199: ** -------------
200: ** This function parses the contents of a "basic" challenge
201: ** and stores the challenge in our authentication information datebase.
202: ** We also store the realm in the request object which will help finding
203: ** the right set of credentials to generate.
204: ** The function is a callback function for the AA handler.
205: */
2.36 ! frystyk 206: PUBLIC int HTBasic_parse (HTRequest * request, void * context, int status)
2.32 frystyk 207: {
2.36 ! frystyk 208: HTAssocList * challenge = HTRequest_challenge(request);
! 209: if (request && challenge) {
! 210: char * p = HTAssocList_findObject(challenge, BASIC_AUTH);
! 211: char * realm = HTNextField(&p);
! 212: char * rm = HTNextField(&p);
2.32 frystyk 213: /*
2.36 ! frystyk 214: ** If valid challenge then make a template for the resource and
! 215: ** store this information in our authentication URL Tree
2.32 frystyk 216: */
2.36 ! frystyk 217: if (realm && !strcasecomp(realm, "realm") && rm) {
! 218: char * url = HTAnchor_physical(HTRequest_anchor(request));
! 219: char * tmplate = make_template(url);
! 220: HTBasic * basic = HTBasic_new();
! 221: if (AUTH_TRACE) HTTrace("Basic Parse. Realm `%s\' found\n", rm);
! 222: HTAA_addNode(BASIC_AUTH, rm, tmplate, basic);
! 223: HTRequest_setRealm(request, rm);
! 224: HT_FREE(tmplate);
2.1 luotonen 225: }
2.36 ! frystyk 226: return HT_OK;
2.1 luotonen 227: }
2.36 ! frystyk 228: if (AUTH_TRACE) HTTrace("Auth........ No challenges found\n");
! 229: return HT_OK;
2.7 luotonen 230: }
2.1 luotonen 231:
232:
Webmaster