/* function secure(keyFile: Path, certFile: Path!, protocols: Array? = null, ciphers: Array? = null): Void */ static EjsObj *hs_secure(Ejs *ejs, EjsHttpServer *sp, int argc, EjsObj **argv) { #if ME_COM_SSL EjsArray *protocols; cchar *token; int mask, protoMask, i; if (sp->ssl == 0 && ((sp->ssl = mprCreateSsl(1)) == 0)) { return 0; } if (!ejsIs(ejs, argv[0], Null)) { mprSetSslKeyFile(sp->ssl, ejsToMulti(ejs, argv[0])); } if (!ejsIs(ejs, argv[1], Null)) { mprSetSslCertFile(sp->ssl, ejsToMulti(ejs, argv[1])); } if (argc >= 3 && ejsIs(ejs, argv[2], Array)) { protocols = (EjsArray*) argv[2]; protoMask = 0; for (i = 0; i < protocols->length; i++) { token = ejsToMulti(ejs, ejsGetProperty(ejs, protocols, i)); mask = -1; if (*token == '-') { token++; mask = 0; } else if (*token == '+') { token++; } if (scaselesscmp(token, "SSLv2") == 0) { protoMask &= ~(MPR_PROTO_SSLV2 & ~mask); protoMask |= (MPR_PROTO_SSLV2 & mask); } else if (scaselesscmp(token, "SSLv3") == 0) { protoMask &= ~(MPR_PROTO_SSLV3 & ~mask); protoMask |= (MPR_PROTO_SSLV3 & mask); } else if (scaselesscmp(token, "TLSv1") == 0) { protoMask &= ~(MPR_PROTO_TLSV1 & ~mask); protoMask |= (MPR_PROTO_TLSV1 & mask); } else if (scaselesscmp(token, "ALL") == 0) { protoMask &= ~(MPR_PROTO_ALL & ~mask); protoMask |= (MPR_PROTO_ALL & mask); } } mprSetSslProtocols(sp->ssl, protoMask); } if (argc >= 4 && ejsIs(ejs, argv[3], Array)) { mprSetSslCiphers(sp->ssl, ejsToMulti(ejs, argv[3])); } #else ejsThrowReferenceError(ejs, "SSL support was not included in the build"); #endif return 0; }
/* function [get|put|delete|post...](uri = null, ...data): Http */ static EjsHttp *startHttpRequest(Ejs *ejs, EjsHttp *hp, char *method, int argc, EjsObj **argv) { EjsArray *args; EjsByteArray *data; EjsNumber *written; EjsUri *uriObj; HttpConn *conn; ssize nbytes; conn = hp->conn; hp->responseCache = 0; hp->requestContentCount = 0; mprFlushBuf(hp->responseContent); if (argc >= 1 && !ejsIs(ejs, argv[0], Null)) { uriObj = (EjsUri*) argv[0]; hp->uri = httpUriToString(uriObj->uri, HTTP_COMPLETE_URI); } if (argc == 2 && ejsIs(ejs, argv[1], Array)) { args = (EjsArray*) argv[1]; if (args->length > 0) { data = ejsCreateByteArray(ejs, -1); written = ejsWriteToByteArray(ejs, data, 1, &argv[1]); mprPutBlockToBuf(hp->requestContent, (char*) data->value, (int) written->value); mprAddNullToBuf(hp->requestContent); assert(written > 0); } } if (hp->uri == 0) { ejsThrowArgError(ejs, "URL is not defined"); return 0; } if (method && strcmp(hp->method, method) != 0) { hp->method = sclone(method); } if (hp->method == 0) { ejsThrowArgError(ejs, "HTTP Method is not defined"); return 0; } if (hp->certFile) { if (!hp->ssl) { hp->ssl = mprCreateSsl(0); } mprSetSslCertFile(hp->ssl, hp->certFile); if (!hp->keyFile) { ejsThrowStateError(ejs, "Must define a Http.key to use with a certificate"); } mprSetSslKeyFile(hp->ssl, hp->keyFile); } if (hp->caFile) { if (!hp->ssl) { hp->ssl = mprCreateSsl(0); } mprSetSslCaFile(hp->ssl, hp->caFile); } if (httpConnect(conn, hp->method, hp->uri, hp->ssl) < 0) { ejsThrowIOError(ejs, "Cannot issue request for \"%s\"", hp->uri); return 0; } if (mprGetBufLength(hp->requestContent) > 0) { nbytes = httpWriteBlock(conn->writeq, mprGetBufStart(hp->requestContent), mprGetBufLength(hp->requestContent), HTTP_BLOCK); if (nbytes < 0) { ejsThrowIOError(ejs, "Cannot write request data for \"%s\"", hp->uri); return 0; } else if (nbytes > 0) { assert(nbytes == mprGetBufLength(hp->requestContent)); mprAdjustBufStart(hp->requestContent, nbytes); hp->requestContentCount += nbytes; } httpFinalize(conn); } httpNotify(conn, HTTP_EVENT_WRITABLE, 0); if (conn->async) { httpEnableConnEvents(hp->conn); } return hp; }
static int parseArgs(int argc, char **argv) { char *argp, *key, *value; int i, setWorkers, nextArg, ssl; setWorkers = 0; ssl = 0; for (nextArg = 1; nextArg < argc; nextArg++) { argp = argv[nextArg]; if (*argp != '-') { break; } if (smatch(argp, "--auth")) { if (nextArg >= argc) { return showUsage(); } else { app->authType = slower(argv[++nextArg]); } } else if (smatch(argp, "--benchmark") || smatch(argp, "-b")) { app->benchmark++; } else if (smatch(argp, "--ca")) { if (nextArg >= argc) { return showUsage(); } else { app->ca = sclone(argv[++nextArg]); if (!mprPathExists(app->ca, R_OK)) { mprError("Cannot find ca file %s", app->ca); return MPR_ERR_BAD_ARGS; } } ssl = 1; } else if (smatch(argp, "--cert")) { if (nextArg >= argc) { return showUsage(); } else { app->cert = sclone(argv[++nextArg]); if (!mprPathExists(app->cert, R_OK)) { mprError("Cannot find cert file %s", app->cert); return MPR_ERR_BAD_ARGS; } } ssl = 1; } else if (smatch(argp, "--chunk")) { if (nextArg >= argc) { return showUsage(); } else { value = argv[++nextArg]; app->chunkSize = atoi(value); if (app->chunkSize < 0) { mprError("Bad chunksize %d", app->chunkSize); return MPR_ERR_BAD_ARGS; } } } else if (smatch(argp, "--ciphers")) { if (nextArg >= argc) { return showUsage(); } else { app->ciphers = sclone(argv[++nextArg]); } ssl = 1; } else if (smatch(argp, "--continue") || smatch(argp, "-c")) { app->continueOnErrors++; } else if (smatch(argp, "--cookie")) { if (nextArg >= argc) { return showUsage(); } else { mprAddItem(app->headers, mprCreateKeyPair("Cookie", argv[++nextArg], 0)); } } else if (smatch(argp, "--data")) { if (nextArg >= argc) { return showUsage(); } else { if (app->bodyData == 0) { app->bodyData = mprCreateBuf(-1, -1); } mprPutStringToBuf(app->bodyData, argv[++nextArg]); } } else if (smatch(argp, "--debugger") || smatch(argp, "-D")) { mprSetDebugMode(1); app->retries = 0; app->timeout = MAXINT; } else if (smatch(argp, "--delete")) { app->method = "DELETE"; } else if (smatch(argp, "--form") || smatch(argp, "-f")) { if (nextArg >= argc) { return showUsage(); } else { if (app->formData == 0) { app->formData = mprCreateList(-1, 0); } addFormVars(argv[++nextArg]); } } else if (smatch(argp, "--header")) { if (nextArg >= argc) { return showUsage(); } else { key = argv[++nextArg]; if ((value = strchr(key, ':')) == 0) { mprError("Bad header format. Must be \"key: value\""); return MPR_ERR_BAD_ARGS; } *value++ = '\0'; while (isspace((uchar) *value)) { value++; } mprAddItem(app->headers, mprCreateKeyPair(key, value, 0)); } } else if (smatch(argp, "--host")) { if (nextArg >= argc) { return showUsage(); } else { app->host = argv[++nextArg]; if (*app->host == ':') { app->host = &app->host[1]; } if (isPort(app->host)) { app->host = sfmt("http://127.0.0.1:%s", app->host); } else { app->host = sclone(app->host); } } } else if (smatch(argp, "--iterations") || smatch(argp, "-i")) { if (nextArg >= argc) { return showUsage(); } else { app->iterations = atoi(argv[++nextArg]); } } else if (smatch(argp, "--key")) { if (nextArg >= argc) { return showUsage(); } else { app->key = sclone(argv[++nextArg]); if (!mprPathExists(app->key, R_OK)) { mprError("Cannot find key file %s", app->key); return MPR_ERR_BAD_ARGS; } } ssl = 1; } else if (smatch(argp, "--log") || smatch(argp, "-l")) { if (nextArg >= argc) { return showUsage(); } else { mprStartLogging(argv[++nextArg], 0); } } else if (smatch(argp, "--method") || smatch(argp, "-m")) { if (nextArg >= argc) { return showUsage(); } else { app->method = argv[++nextArg]; } } else if (smatch(argp, "--out") || smatch(argp, "-o")) { if (nextArg >= argc) { return showUsage(); } else { app->outFilename = sclone(argv[++nextArg]); } } else if (smatch(argp, "--noout") || smatch(argp, "-n") || smatch(argp, "--quiet") || smatch(argp, "-q")) { app->noout++; } else if (smatch(argp, "--nofollow")) { app->nofollow++; } else if (smatch(argp, "--password") || smatch(argp, "-p")) { if (nextArg >= argc) { return showUsage(); } else { app->password = sclone(argv[++nextArg]); } } else if (smatch(argp, "--post")) { app->method = "POST"; } else if (smatch(argp, "--printable")) { app->printable++; } else if (smatch(argp, "--protocol")) { if (nextArg >= argc) { return showUsage(); } else { app->protocol = supper(argv[++nextArg]); } } else if (smatch(argp, "--provider")) { /* Undocumented SSL provider selection */ if (nextArg >= argc) { return showUsage(); } else { app->provider = sclone(argv[++nextArg]); } ssl = 1; } else if (smatch(argp, "--put")) { app->method = "PUT"; } else if (smatch(argp, "--range")) { if (nextArg >= argc) { return showUsage(); } else { if (app->ranges == 0) { app->ranges = sfmt("bytes=%s", argv[++nextArg]); } else { app->ranges = srejoin(app->ranges, ",", argv[++nextArg], NULL); } } } else if (smatch(argp, "--retries") || smatch(argp, "-r")) { if (nextArg >= argc) { return showUsage(); } else { app->retries = atoi(argv[++nextArg]); } } else if (smatch(argp, "--self")) { /* Undocumented. Allow self-signed certs. Users should just not set --verify */ app->verifyIssuer = 0; ssl = 1; } else if (smatch(argp, "--sequence")) { app->sequence++; } else if (smatch(argp, "--showHeaders") || smatch(argp, "--show") || smatch(argp, "-s")) { app->showHeaders++; } else if (smatch(argp, "--showStatus") || smatch(argp, "--showCode")) { app->showStatus++; } else if (smatch(argp, "--single") || smatch(argp, "-s")) { app->singleStep++; } else if (smatch(argp, "--text")) { app->text++; } else if (smatch(argp, "--threads") || smatch(argp, "-t")) { if (nextArg >= argc) { return showUsage(); } else { app->loadThreads = atoi(argv[++nextArg]); } } else if (smatch(argp, "--timeout")) { if (nextArg >= argc) { return showUsage(); } else { app->timeout = atoi(argv[++nextArg]) * MPR_TICKS_PER_SEC; } } else if (smatch(argp, "--upload") || smatch(argp, "-u")) { app->upload++; } else if (smatch(argp, "--user") || smatch(argp, "--username")) { if (nextArg >= argc) { return showUsage(); } else { app->username = argv[++nextArg]; } // DEPRECATE validate. Preserve verify. } else if (smatch(argp, "--validate") || smatch(argp, "--verify")) { app->verifyPeer = 1; ssl = 1; } else if (smatch(argp, "--verbose") || smatch(argp, "-v")) { app->verbose++; } else if (smatch(argp, "--version") || smatch(argp, "-V")) { mprEprintf("%s %s\n" "Copyright (C) Embedthis Software 2003-2013\n" "Copyright (C) Michael O'Brien 2003-2013\n", BIT_TITLE, BIT_VERSION); exit(0); } else if (smatch(argp, "--workerTheads") || smatch(argp, "-w")) { if (nextArg >= argc) { return showUsage(); } else { app->workers = atoi(argv[++nextArg]); } setWorkers++; } else if (smatch(argp, "--zero")) { app->zeroOnErrors++; } else if (smatch(argp, "--")) { nextArg++; break; } else if (smatch(argp, "-")) { break; } else { return showUsage(); } } if (argc == nextArg) { return showUsage(); } app->nextArg = nextArg; argc = argc - nextArg; argv = &argv[nextArg]; app->target = argv[argc - 1]; if (--argc > 0) { /* Files present on command line */ app->files = mprCreateList(argc, MPR_LIST_STATIC_VALUES); for (i = 0; i < argc; i++) { mprAddItem(app->files, argv[i]); } } if (!setWorkers) { app->workers = app->loadThreads + 2; } if (app->method == 0) { if (app->bodyData || app->formData || app->upload) { app->method = "POST"; } else if (app->files) { app->method = "PUT"; } else { app->method = "GET"; } } #if BIT_PACK_SSL { HttpUri *uri = httpCreateUri(app->target, 0); if (uri->secure || ssl) { app->ssl = mprCreateSsl(0); if (app->provider) { mprSetSslProvider(app->ssl, app->provider); } if (app->cert) { if (!app->key) { mprError("Must specify key file"); return 0; } mprSetSslCertFile(app->ssl, app->cert); mprSetSslKeyFile(app->ssl, app->key); } if (app->ca) { mprLog(4, "Using CA: \"%s\"", app->ca); mprSetSslCaFile(app->ssl, app->ca); } if (app->verifyIssuer == -1) { app->verifyIssuer = app->verifyPeer ? 1 : 0; } mprVerifySslPeer(app->ssl, app->verifyPeer); mprVerifySslIssuer(app->ssl, app->verifyIssuer); if (app->ciphers) { mprSetSslCiphers(app->ssl, app->ciphers); } } else { mprVerifySslPeer(NULL, 0); } } #else /* Suppress comp warning */ mprNop(&ssl); #endif return 0; }