minihttp.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 2,205 行 · 第 1/5 页
C
2,205 行
numParams = httpparse_count_params(req); SSM_DEBUG("Found %d params\n", numParams); req->paramNames = (char **) PR_Calloc(numParams+1, sizeof(char *)); if (!req->paramNames) goto loser; req->paramValues = (char **) PR_Calloc(numParams+1, sizeof(char *)); if (!req->paramValues) goto loser; httpparse_unescape_param(req->params); /* Put the params in their place. */ for(i=0, c = start = req->params; i < numParams; i++) { /* Get the parameter name. */ while((*c) && (*c != '=') && (*c != '&')) c++; req->paramNames[i] = start; /* name goes here */ if (*c == '\0') { /* reached end of params while looking for a name. leave the value null, end. */ break; } /* save off the delimiter so that we can decide how to proceed */ d = *c; /* null out the delimiter so that the param name is usable */ *c++ = '\0'; start = c; if (d == '&') /* found a name but no value. leave value null, loop back. */ continue; /* Now, copy the value. */ req->paramValues[i] = start; /* If we have more params to process, tie off the end of this parameter value. */ if (i != (numParams-1)) { while((*c) && (*c != '&')) /* (*c) check just to be safe */ { if (*c == '~') *c = '&'; c++; } *c++ = '\0'; start = c; /* get ready to mark off next parameter */ } SSM_DEBUG("Param Name: %s, Param Value: %s\n", req->paramNames[i], req->paramValues[i]); } goto done; loser: PR_FREEIF(req->paramNames); PR_FREEIF(req->paramValues); done: return rv;}/* Parse an incoming request. */static SSMStatushttp_parse_request(HTTPRequest *req){ char *line, *chunk = req->reqbuf; char *b, *e; /* beginning and end of something we want */ char *p; /* beginning of params */ SECItem tmpItem = {siBuffer, NULL, 0}; while ((line = nextLine(&chunk)) != NULL) { /* Is it a request we're interested in? */ if (!STRNCASECMP(line, "GET ", 4)) { SSM_DEBUG("Parsing GET request: `%s'\n", line); /* Parse the GET request. */ b = strchr(line, ' '); e = strrchr(line, ' '); if (!b) SSM_DEBUG("Couldn't find beginning of file!"); if (!e) SSM_DEBUG("Couldn't find end of file!"); if ((!b) || (!e)) continue; while ((IS_WHITESPACE(*b)) && (b < e)) b++; while ((IS_WHITESPACE(*e)) && (b < e)) e--; e++; *e = '\0'; if (*b == '/') b++; /* move past the first slash */ req->handlerName = b; /* this is the command handler */ SSM_DEBUG("Base ref: `%s'.\n", req->handlerName); p = strchr(b, '?'); if (p) { *p++ = '\0'; req->params = p; SSM_DEBUG("Params: `%s'.\n", req->params ? req->params : "(none)"); httpparse_parse_params(req); } continue; } /* If we get here, then we assume we have a header with a colon in it (i.e. a header line other than the GET). We're interested in anything after the colon. */ b = strchr(line, ':'); if (!b) /* Dunno what to do, ignore this line */ continue; do { b++; } while (IS_WHITESPACE(*b)); if (!STRNCASECMP(line, "User-Agent", 10)) { SSM_DEBUG("Found User-Agent: `%s'.\n", b); req->agent = b; } else if (!STRNCASECMP(line, "Accept-Language", 15)) { SSM_DEBUG("Found Accept-Language: `%s'.\n", b); req->language = b; } else if (!STRNCASECMP(line, "Accept-Charset", 14)) { SSM_DEBUG("Found Accept-Charset: `%s'.\n", b); req->charset = b; } else if (!STRNCASECMP(line, "Referer", 7)) { /* Make the new request inherit the same target as * its referer */ req->referer = b; } else if (!STRNCASECMP(line, "Authorization", 13)) { SECStatus srv; SSM_DEBUG("Found Authorization: `%s'.\n", b); /* If the auth type is basic, process the auth info. */ if (!STRNCASECMP(b, "Basic", 5)) { PRIntn len; /* move to the auth info itself */ while ((*b) && (!IS_WHITESPACE(*b))) b++; while ((*b) && (IS_WHITESPACE(*b))) b++; /* decode base-64. yikes. */ srv = ATOB_ConvertAsciiToItem(&tmpItem, b); if (srv == SECSuccess) { /* We need to copy the ascii over and NULL * terminate it correctly becuase the * Base64 decoder doesn't guarantee that. */ char *w = (char *) PR_Malloc(tmpItem.len+1); PL_strncpy(w, (char *) tmpItem.data, tmpItem.len); w[tmpItem.len] = '\0'; SSM_DEBUG("Decoded auth: '%s'.\n", w); PR_Free(tmpItem.data); tmpItem.data = (unsigned char *) w; len = tmpItem.len; /* divide control RID (username) and nonce (password). ### mwelch - I walk manually through this because the string isn't null-terminated. */ while((len > 0) && (*w != ':')) { w++; len--; } if (len > 0) { PRIntn ridLen = tmpItem.len-len; req->ctrlrid = (char *) PR_CALLOC(ridLen+1); req->password = (char *) PR_CALLOC(len+1); if (req->ctrlrid) { strncpy(req->ctrlrid, (char *) tmpItem.data, (unsigned long) ridLen); SSM_DEBUG("ctrlrid: %s\n", req->ctrlrid); } else SSM_DEBUG("Couldn't allocate a ctrlrid.\n"); if (req->password) { /* Skip over the colon separating rid and nonce. */ strncpy(req->password, ++w, --len); SSM_DEBUG("password: %s\n", req->password); } else SSM_DEBUG("Couldn't allocate a password.\n"); } else SSM_DEBUG("Couldn't find ':' in between ctrlrid and password.\n"); SECITEM_FreeItem(&tmpItem, PR_FALSE); } else SSM_DEBUG("srv %ld decoding basic auth info.\n", (long) srv); } else SSM_HTTPReportError(req, HTTP_UNAUTHORIZED); } } return SSM_SUCCESS;}/* Read an HTTP request. */SSMStatushttp_read_request(PRFileDesc *sock, HTTPRequest **returnReq){ PRIntn read; PRBool detectEOR = PR_FALSE; /* Have we detected the end of the request? */ char buf[LINESIZE]; SSMStatus rv = SSM_SUCCESS; PRUint32 tail; HTTPRequest *req = NULL; if (!sock || !returnReq) { rv = PR_INVALID_ARGUMENT_ERROR; goto loser; } /* Set up the request object. */ req = http_request_create(sock); if (!req) goto loser; /* Get the request in chunks. */ while(!detectEOR) { PR_SetError(0, 0); /* reset so that error detect below works */ read = PR_Recv(sock, buf, LINESIZE, 0, PR_INTERVAL_NO_TIMEOUT); if (read <= 0) { rv = PR_GetError(); if (rv == PR_SUCCESS) rv = PR_GetOSError(); goto loser; } /* Add the latest bits onto the end of the request */ rv = http_request_add_chunk(req, buf, read); if (rv != SSM_SUCCESS) goto loser; /* Look for LF+LF, CR+CR, CR+LF+CR+LF, or (heh) LF+CR+LF+CR. If we find any of these, it means that we have the end of request. */ (void) memcpy((char *) &tail, &(req->reqbuf[req->slen-4]), 4); /* Do the four-byte comparisons first, they're easier and more common */ if ((tail == 0x0d0a0d0a) || (tail == 0x0a0d0a0d)) detectEOR = PR_TRUE; else { /* Look for CR+CR or LF+LF. */ tail &= 0x0000FFFF; if ((tail == 0x00000d0d) || (tail == 0x00000a0a)) detectEOR = PR_TRUE; } } /* duplicate the buffer, use one copy for parsing */ req->rawreqbuf = (char *) PR_CALLOC(req->slen+1); if (!req->rawreqbuf) goto loser; (void) memcpy(req->rawreqbuf, req->reqbuf, req->slen+1); goto done; loser: if (rv == SSM_SUCCESS) rv = SSM_FAILURE; done: if (returnReq) *returnReq = req; return rv;}static SSMStatusssm_http_param_from_index(HTTPRequest *req, const char *key, char **value, int startIndex, int *valueIndex){ PRUint32 i; SSMStatus rv = SSM_FAILURE; if (!value) return rv; *value = NULL; /* in case we fail */ *valueIndex = -1; for(i=startIndex; i < req->numParams; i++) { if (req->paramNames[i] && (!PL_strcmp(req->paramNames[i], key))) { *value = req->paramValues[i]; *valueIndex = i; rv = SSM_SUCCESS; break; } } if (rv != SSM_SUCCESS) SSM_DEBUG("HTTPParamValue: Error %d attempting to get parameter '%s'.\n" , rv, key); return rv;}SSMStatusSSM_HTTPParamValueMultiple(HTTPRequest *req, const char *key, SSMHTTPParamMultValues *values){ int currIndex, nextIndex; unsigned int i, numVars = 0; char *tmp; SSMStatus rv; /* * First, let's count the number of parameters there are, the fill in * the array. */ PR_ASSERT(values->key == NULL && values->values == NULL); for (i=0; i<req->numParams; i++) { rv = ssm_http_param_from_index(req,key,&tmp,i,&currIndex); if (rv != SSM_SUCCESS || currIndex == -1) { break; } numVars++; i = currIndex; } if (numVars == 0) { goto loser; } values->values = SSM_NEW_ARRAY(char*, numVars); currIndex = 0; for (i=0; i<numVars;i++) { rv = ssm_http_param_from_index(req,key,&values->values[i], currIndex, &nextIndex); if (rv != SSM_SUCCESS || nextIndex == -1) { break; } currIndex = nextIndex+1; } values->numValues = numVars; values->key = key; return SSM_SUCCESS; loser: PR_FREEIF(values->values); values->values = NULL; values->numValues=0; return SSM_FAILURE;}SSMStatusSSM_HTTPParamValue(HTTPRequest *req, const char *key, char **value){ int valueIndex; return ssm_http_param_from_index(req, key, value, 0, &valueIndex);}static SSMStatushttp_authenticate(HTTPRequest *req){ SSMStatus rv = SSM_FAILURE; SSMResource *res; SSMControlConnection *ctrlconn = NULL;#ifdef ALLOW_STANDALONE if (standalone) { PR_ASSERT(standalone_conn); req->ctrlconn = standalone_conn; SSM_DEBUG("authenticate: Standalone mode, passing through.\n"); return SSM_SUCCESS; }#endif /* do we have auth information? */ if ((req->ctrlrid) && (req->password)) { /* Get the control connection object. */ rv = SSM_RIDTextToResource(req, req->ctrlrid, &res); if (rv == SSM_SUCCESS) { ctrlconn = (SSMControlConnection *) res; req->ctrlconn = ctrlconn; /* Verify restype and nonce. */ if ((!SSM_IsAKindOf(res, SSM_RESTYPE_CONTROL_CONNECTION)) || (PL_strcmp(req->password, ctrlconn->m_nonce))) { SSM_DEBUG("------------------------------\n"); SSM_DEBUG("Password doesn't match nonce.\n"); SSM_DEBUG("Nonce: %s\n", ctrlconn->m_nonce); SSM_DEBUG("Submitted password: %s\n", req->password); SSM_DEBUG("------------------------------\n"); PR_ASSERT(!"Couldn't authenticate this connection\n"); rv = SSM_FAILURE; } } else SSM_DEBUG("authenticate: Couldn't find a control connection.\n"); } else { if (!req->ctrlrid) SSM_DEBUG("authenticate: No ctrlrid available.\n"); else if (!req->password) SSM_DEBUG("authenticate: No password available.\n"); } if (rv != SSM_SUCCESS) req->httprv = HTTP_UNAUTHORIZED; else req->ctrlconn = ctrlconn; /* type must check out */ return rv;}/* Returns the suffix of the filename, if it exists. */char *http_find_suffix(HTTPRequest *req){ char *result = NULL; char *c; c = req->filename; if (!c) return result; while(*c && (*c != '.')) c++; if (*c) result = ++c; else result = NULL;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?