📄 minihttp.c
字号:
/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- *//* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Netscape security libraries. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. *//* Routines which implement a mini-HTTP server for PSM. This module is intended for low-volume use, such as to present a security advisor dialog and respond to form posts from same. Created by Mark Welch <mwelch@netscape.com> 98 October*/#include "minihttp.h"#include "resource.h"#include "dataconn.h"#include "prtypes.h"#include "prthread.h"#include "prprf.h"#include "serv.h"#include "kgenctxt.h"#include "base64.h"#include "nlsutil.h"#include "textgen.h"#include "certlist.h"#include "ssldlgs.h"#include "ctrlconn.h"#include "pkcs11ui.h"#include "oldfunc.h"#include "certres.h"#include "advisor.h"#include <string.h>#define SSM_HTTP_REQUEST_CHUNKSIZE 256#define SSM_STANDALONE_HTTP_PORT 9999PRUint32 httpListenPort = 0;PRThread *httpListenThread = NULL;#ifdef ALLOW_STANDALONEPRBool standalone = 0;SSMControlConnection *standalone_conn = NULL;SSMStatus SSMControlConnection_SetupNSS(SSMControlConnection *ctrl);#endif/* A command handler registration object */typedef struct CommandHandlerEntry{ const char *key; SSMCommandHandlerFunc func;} CommandHandlerEntry;static SSMCollection *http_handlers = NULL;SSMStatus SSM_HTTPFindCommandHandler(const char *name, SSMCommandHandlerFunc *func);SSMStatus SSM_HTTPOKCancelHandler(HTTPRequest *req);SSMStatus SSM_HTTPFormSubmitHandler(HTTPRequest *req);SSMStatus SSM_HTTPCloseIfCancel(HTTPRequest *req);/* ------------------------------------------- Register command handlers here -------------------------------------------*/static SSMStatushttp_register_handlers(void){ SSMStatus rv = SSM_SUCCESS; /* Default command handler */ rv = SSM_HTTPRegisterCommandHandler("get", SSM_HTTPDefaultCommandHandler); if (rv != SSM_SUCCESS) goto loser; rv = SSM_HTTPRegisterCommandHandler("getbin", SSM_HTTPGetBinaryHandler); if (rv != SSM_SUCCESS) goto loser; rv = SSM_HTTPRegisterCommandHandler("resmonitor", SSM_HTTPMonitorResourceHandler); if (rv != SSM_SUCCESS) goto loser; rv = SSM_HTTPRegisterCommandHandler("shutdown", SSM_HTTPShutdownResourceHandler); if (rv != SSM_SUCCESS) goto loser;#if 0 rv = SSM_HTTPRegisterCommandHandler("setLocale", SSM_SetLocaleCommandHandler); if (rv != SSM_SUCCESS) goto loser; rv = SSM_HTTPRegisterCommandHandler("reloadText", SSM_ReloadTextCommandHandler); if (rv != SSM_SUCCESS) goto loser;#endif rv = SSM_HTTPRegisterCommandHandler("BCAButton", SSM_HTTPBadClientAuthButtonHandler); if (rv != SSM_SUCCESS) goto loser; rv = SSM_HTTPRegisterCommandHandler("unknownIssuerStep1", SSM_HTTPUnknownIssuerStep1ButtonHandler); if (rv != SSM_SUCCESS) goto loser; rv = SSM_HTTPRegisterCommandHandler("tokenSelect", SSMTokenUI_CommandHandler); if (rv != SSM_SUCCESS) goto loser; rv = SSM_HTTPRegisterCommandHandler("SetFIPSMode", SSM_SetFIPSModeCommandHandler); if (rv != SSM_SUCCESS) goto loser; rv = SSM_HTTPRegisterCommandHandler("PKCS11ShowSlots", SSM_ShowSlotsCommandHandler); if (rv != SSM_SUCCESS) goto loser; rv = SSM_HTTPRegisterCommandHandler("PKCS11ShowSlot", SSM_ShowSlotCommandHandler); if (rv != SSM_SUCCESS) goto loser; rv = SSM_HTTPRegisterCommandHandler("PKCS11LoginSlot", SSM_LoginSlotCommandHandler); if (rv != SSM_SUCCESS) goto loser; rv = SSM_HTTPRegisterCommandHandler("PKCS11LogoutSlot", SSM_LogoutSlotCommandHandler); if (rv != SSM_SUCCESS) goto loser; rv = SSM_HTTPRegisterCommandHandler("PKCS11LogoutAllSlots", SSM_LogoutAllSlotsCommandHandler); if (rv != SSM_SUCCESS) goto loser; rv = SSM_HTTPRegisterCommandHandler("OKButton", SSM_OKButtonCommandHandler); if (rv != SSM_SUCCESS) goto loser; /* handler for the second step is called form formsubmit_handler * from finish_import_cert form submission */ rv = SSM_HTTPRegisterCommandHandler("importCACert1", SSM_CertCAImportCommandHandler1); if (rv != SSM_SUCCESS) goto loser; rv = SSM_HTTPRegisterCommandHandler("check_for_cancel", SSM_SubmitFormFromButtonHandler); if (rv != SSM_SUCCESS) goto loser; rv = SSM_HTTPRegisterCommandHandler("delete_certificate", SSM_DeleteCertHandler); if (rv != SSM_SUCCESS) goto loser; rv = SSM_HTTPRegisterCommandHandler("ldap_request_others", SSM_ProcessLDAPRequestHandler); if (rv != SSM_SUCCESS) goto loser; rv = SSM_HTTPRegisterCommandHandler("remove_privileges", SSM_RemovePrivilegesHandler); if (rv != SSM_SUCCESS) goto loser; /* Hello World example */ rv = SSM_HTTPRegisterCommandHandler("hello", SSM_HTTPHelloWorld); if (rv != SSM_SUCCESS) goto loser; /* Unicode Hello World example */ rv = SSM_HTTPRegisterCommandHandler("hello_unicode", SSM_HTTPHelloWorldWithNLS); if (rv != SSM_SUCCESS) goto loser; rv = SSM_HTTPRegisterCommandHandler("ok_cancel_handler", SSM_HTTPOKCancelHandler); if (rv != SSM_SUCCESS) goto loser; rv = SSM_HTTPRegisterCommandHandler("cert", SSM_HTTPCertListHandler); if (rv != SSM_SUCCESS) goto loser; /* Put your command handler here */ rv = SSM_HTTPRegisterCommandHandler("formsubmit_handler", SSM_HTTPFormSubmitHandler); if (rv != SSM_SUCCESS) goto loser; rv = SSM_HTTPRegisterCommandHandler("close_if_cancel", SSM_HTTPCloseIfCancel); if (rv != SSM_SUCCESS) goto loser; goto done; loser: if (rv == SSM_SUCCESS) rv = SSM_FAILURE; done: return rv;}static voidhttp_request_destroy(HTTPRequest *r){ if (r->target) SSM_FreeResource(r->target); PR_FREEIF(r->reqbuf); PR_FREEIF(r->rawreqbuf); PR_FREEIF(r->hdrbuf); PR_FREEIF(r->filename); PR_FREEIF(r->paramNames); PR_FREEIF(r->paramValues); PR_FREEIF(r->ctrlrid); PR_FREEIF(r->password); PR_FREEIF(r->errormsg); if ((r->sock) && (!r->keepSock)) { SSMStatus rv; /* we should shut down before closing */ rv = PR_Shutdown(r->sock, PR_SHUTDOWN_BOTH); if (rv != PR_SUCCESS) { SSM_DEBUG("Tried to shutdown socket, but got return val %d\n" "\tWill try to close socket anywary.\n", rv); } /* close the socket */ rv = PR_Close(r->sock); if (rv != PR_SUCCESS) { SSM_DEBUG("Error trying to close http socket: %d\n",rv); } } else if (!r->sock) SSM_DEBUG("Hey! There's no socket to close!\n"); (void) memset(r, 0, sizeof(HTTPRequest)); PR_Free(r);}static SSMStatushttp_request_grow_request(HTTPRequest *req, PRUint32 newSize){ PRUint32 newLimit = req->len; char *newPtr; SSMStatus rv = SSM_SUCCESS; /* If we're already big enough, we don't need to do anything. */ if (newSize <= req->len) return SSM_SUCCESS; /* Ensure that the request is sized to the next power of two above (newSize). (This cuts down on the number of reallocations.) */ if (newLimit == 0) newLimit = 1; while(newLimit < newSize) newLimit <<= 1; if (newLimit == 0) { /* this should never happen */ rv = SSM_FAILURE; goto loser; } /* Reallocate the string to the new length. */ newPtr = (char *) PR_REALLOC(req->reqbuf, newLimit); if (!newPtr) goto loser; req->reqbuf = newPtr; req->len = newLimit; goto done; loser: if (rv == SSM_SUCCESS) rv = SSM_FAILURE; done: return rv;}static SSMStatushttp_request_add_chunk(HTTPRequest *req, char *newChunk, PRUint32 len){ SSMStatus rv = http_request_grow_request(req, req->slen + len + 1); if (rv == SSM_SUCCESS) { char *c = req->reqbuf + req->slen; strncpy(c, newChunk, len); *(c + len) = '\0'; /* null terminate the end */ req->slen += len; } return rv;}static HTTPRequest *http_request_create(PRFileDesc *sock){ PRUint32 size = SSM_HTTP_REQUEST_CHUNKSIZE; HTTPRequest *result = (HTTPRequest *) PR_CALLOC(sizeof(HTTPRequest)); if (!result) goto loser; if (http_request_grow_request(result, size) != SSM_SUCCESS) goto loser; result->processText = PR_TRUE; /* assume we're acting on text */ result->sock = sock; /* REMOVED CALL */; goto done; loser: if (result) { http_request_destroy(result); result = NULL; } done: return result;}/* Eat a line of text from the request. Advances (*buf) to the next line. */static char *nextLine(char **buf){ char *rv = *buf; char *c = *buf; if (!*c) return NULL; while (!IS_EOL(*c) && (*c)) c++; /* Blank out as many consecutive newline characters as we have. */ while (IS_EOL(*c)) *c++ = '\0'; *buf = c; return rv;}PRInt32httpparse_count_params(HTTPRequest *req){ char *c; PRInt32 numParams = req->params ? 1 : 0; if (numParams > 0) { /* find the parameters. */ for(c = req->params;*c != '\0';c++) { if (*c == '&') numParams++; } } req->numParams = numParams; return numParams;}static voidhttpparse_unescape_param(char* str){ char *plusSign, *percentSign; /*First look for all of the '+' and convert them to spaces */ plusSign = str; while ((plusSign=strchr(plusSign, '+')) != NULL) { *plusSign = ' '; } percentSign = str; while ((percentSign=strchr(percentSign, '%')) != NULL) { char string[3]; int value; string[0] = percentSign[1]; string[1] = percentSign[2]; string[2] = '\0'; PR_sscanf(string,"%x", &value); *percentSign = (char)value; memmove(&percentSign[1], &percentSign[3], 1+strlen(&percentSign[3])); }}SSMStatushttpparse_parse_params(HTTPRequest *req)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -