📄 ssl_engine_pphrase.c
字号:
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "Init: SSLPassPhraseDialog builtin is not " "supported on Win32 (key file " "%s)", szPath); ssl_die(); }#endif /* WIN32 */ /* * Ok, anything else now means a fatal error. */ if (cpPassPhraseCur == NULL) { if (nPassPhraseDialogCur && pkey_mtime && !(isterm = isatty(fileno(stdout)))) /* XXX: apr_isatty() */ { ap_log_error(APLOG_MARK, APLOG_ERR, 0, pServ, "Init: Unable to read pass phrase " "[Hint: key introduced or changed " "before restart?]"); ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, pServ); } else { ap_log_error(APLOG_MARK, APLOG_ERR, 0, pServ, "Init: Private key not found"); ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, pServ); } if (writetty) { apr_file_printf(writetty, "Apache:mod_ssl:Error: Private key not found.\n"); apr_file_printf(writetty, "**Stopped\n"); } } else { ap_log_error(APLOG_MARK, APLOG_ERR, 0, pServ, "Init: Pass phrase incorrect"); ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, pServ); if (writetty) { apr_file_printf(writetty, "Apache:mod_ssl:Error: Pass phrase incorrect.\n"); apr_file_printf(writetty, "**Stopped\n"); } } ssl_die(); } if (pPrivateKey == NULL) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "Init: Unable to read server private key from " "file %s [Hint: Perhaps it is in a separate file? " " See SSLCertificateKeyFile]", szPath); ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); ssl_die(); } /* * check algorithm type of private key and make * sure only one private key per type is used. */ at = ssl_util_algotypeof(NULL, pPrivateKey); an = ssl_util_algotypestr(at); if (algoKey & at) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "Init: Multiple %s server private keys not " "allowed", an); ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); ssl_die(); } algoKey |= at; /* * Log the type of reading */ if (nPassPhraseDialogCur == 0) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, pServ, "unencrypted %s private key - pass phrase not " "required", an); } else { if (cpPassPhraseCur != NULL) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, pServ, "encrypted %s private key - pass phrase " "requested", an); } else { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, pServ, "encrypted %s private key - pass phrase" " reused", an); } } /* * Ok, when we have one more pass phrase store it */ if (cpPassPhraseCur != NULL) { cpp = (char **)apr_array_push(aPassPhrase); *cpp = cpPassPhraseCur; nPassPhrase++; } /* * Insert private key into the global module configuration * (we convert it to a stand-alone DER byte sequence * because the SSL library uses static variables inside a * RSA structure which do not survive DSO reloads!) */ cp = asn1_table_vhost_key(mc, p, cpVHostID, an); length = i2d_PrivateKey(pPrivateKey, NULL); ucp = ssl_asn1_table_set(mc->tPrivateKey, cp, length); (void)i2d_PrivateKey(pPrivateKey, &ucp); /* 2nd arg increments */ if (nPassPhraseDialogCur != 0) { /* remember mtime of encrypted keys */ asn1 = ssl_asn1_table_get(mc->tPrivateKey, cp); asn1->source_mtime = pkey_mtime; } /* * Free the private key structure */ EVP_PKEY_free(pPrivateKey); } } /* * Let the user know when we're successful. */ if (nPassPhraseDialog > 0) { sc = mySrvConfig(s); if (writetty) { apr_file_printf(writetty, "\n" "OK: Pass Phrase Dialog successful.\n"); } } /* * Wipe out the used memory from the * pass phrase array and then deallocate it */ if (aPassPhrase->nelts) { pphrase_array_clear(aPassPhrase); ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, "Init: Wiped out the queried pass phrases from memory"); } /* Close the pipes if they were opened */ if (readtty) { apr_file_close(readtty); apr_file_close(writetty); readtty = writetty = NULL; } return;}static apr_status_t ssl_pipe_child_create(apr_pool_t *p, const char *progname){ /* Child process code for 'ErrorLog "|..."'; * may want a common framework for this, since I expect it will * be common for other foo-loggers to want this sort of thing... */ apr_status_t rc; apr_procattr_t *procattr; apr_proc_t *procnew; if (((rc = apr_procattr_create(&procattr, p)) == APR_SUCCESS) && ((rc = apr_procattr_io_set(procattr, APR_FULL_BLOCK, APR_FULL_BLOCK, APR_NO_PIPE)) == APR_SUCCESS)) { char **args; const char *pname; apr_tokenize_to_argv(progname, &args, p); pname = apr_pstrdup(p, args[0]); procnew = (apr_proc_t *)apr_pcalloc(p, sizeof(*procnew)); rc = apr_proc_create(procnew, pname, (const char * const *)args, NULL, procattr, p); if (rc == APR_SUCCESS) { /* XXX: not sure if we aught to... * apr_pool_note_subprocess(p, procnew, APR_KILL_AFTER_TIMEOUT); */ writetty = procnew->in; readtty = procnew->out; } } return rc;}static int pipe_get_passwd_cb(char *buf, int length, char *prompt, int verify){ apr_status_t rc; char *p; apr_file_puts(prompt, writetty); buf[0]='\0'; rc = apr_file_gets(buf, length, readtty); apr_file_puts(APR_EOL_STR, writetty); if (rc != APR_SUCCESS || apr_file_eof(readtty)) { memset(buf, 0, length); return 1; /* failure */ } if ((p = strchr(buf, '\n')) != NULL) { *p = '\0'; }#ifdef WIN32 /* XXX: apr_sometest */ if ((p = strchr(buf, '\r')) != NULL) { *p = '\0'; }#endif return 0;}#ifdef SSLC_VERSION_NUMBERint ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify){ void *srv = ssl_pphrase_server_rec;#elseint ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv){#endif SSLModConfigRec *mc; server_rec *s; apr_pool_t *p; apr_array_header_t *aPassPhrase; SSLSrvConfigRec *sc; int *pnPassPhraseCur; char **cppPassPhraseCur; char *cpVHostID; char *cpAlgoType; int *pnPassPhraseDialog; int *pnPassPhraseDialogCur; BOOL *pbPassPhraseDialogOnce; char *cpp; int len = -1; mc = myModConfig((server_rec *)srv); /* * Reconnect to the context of ssl_phrase_Handle() */ s = myCtxVarGet(mc, 1, server_rec *); p = myCtxVarGet(mc, 2, apr_pool_t *); aPassPhrase = myCtxVarGet(mc, 3, apr_array_header_t *); pnPassPhraseCur = myCtxVarGet(mc, 4, int *); cppPassPhraseCur = myCtxVarGet(mc, 5, char **); cpVHostID = myCtxVarGet(mc, 6, char *); cpAlgoType = myCtxVarGet(mc, 7, char *); pnPassPhraseDialog = myCtxVarGet(mc, 8, int *); pnPassPhraseDialogCur = myCtxVarGet(mc, 9, int *); pbPassPhraseDialogOnce = myCtxVarGet(mc, 10, BOOL *); sc = mySrvConfig(s); (*pnPassPhraseDialog)++; (*pnPassPhraseDialogCur)++; /* * When remembered pass phrases are available use them... */ if ((cpp = pphrase_array_get(aPassPhrase, *pnPassPhraseCur)) != NULL) { apr_cpystrn(buf, cpp, bufsize); len = strlen(buf); return len; } /* * Builtin or Pipe dialog */ if (sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN || sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) { char *prompt; int i; if (sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) { if (!readtty) { ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, "Init: Creating pass phrase dialog pipe child " "'%s'", sc->server->pphrase_dialog_path); if (ssl_pipe_child_create(p, sc->server->pphrase_dialog_path) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "Init: Failed to create pass phrase pipe '%s'", sc->server->pphrase_dialog_path); PEMerr(PEM_F_DEF_CALLBACK,PEM_R_PROBLEMS_GETTING_PASSWORD); memset(buf, 0, (unsigned int)bufsize); return (-1); } } ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, "Init: Requesting pass phrase via piped dialog"); } else { /* sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN */#ifdef WIN32 PEMerr(PEM_F_DEF_CALLBACK,PEM_R_PROBLEMS_GETTING_PASSWORD); memset(buf, 0, (unsigned int)bufsize); return (-1);#else /* * stderr has already been redirected to the error_log. * rather than attempting to temporarily rehook it to the terminal, * we print the prompt to stdout before EVP_read_pw_string turns * off tty echo */ apr_file_open_stdout(&writetty, p); ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, "Init: Requesting pass phrase via builtin terminal " "dialog");#endif } /* * The first time display a header to inform the user about what * program he actually speaks to, which module is responsible for * this terminal dialog and why to the hell he has to enter * something... */ if (*pnPassPhraseDialog == 1) { apr_file_printf(writetty, "%s mod_ssl/%s (Pass Phrase Dialog)\n", AP_SERVER_BASEVERSION, MOD_SSL_VERSION); apr_file_printf(writetty, "Some of your private key files are encrypted for security reasons.\n"); apr_file_printf(writetty, "In order to read them you have to provide the pass phrases.\n"); } if (*pbPassPhraseDialogOnce) { *pbPassPhraseDialogOnce = FALSE; apr_file_printf(writetty, "\n"); apr_file_printf(writetty, "Server %s (%s)\n", cpVHostID, cpAlgoType); } /* * Emulate the OpenSSL internal pass phrase dialog * (see crypto/pem/pem_lib.c:def_callback() for details) */ prompt = "Enter pass phrase:"; for (;;) { apr_file_puts(prompt, writetty); if (sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) { i = pipe_get_passwd_cb(buf, bufsize, "", FALSE); } else { /* sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN */ i = EVP_read_pw_string(buf, bufsize, "", FALSE); } if (i != 0) { PEMerr(PEM_F_DEF_CALLBACK,PEM_R_PROBLEMS_GETTING_PASSWORD); memset(buf, 0, (unsigned int)bufsize); return (-1); } len = strlen(buf); if (len < 1) apr_file_printf(writetty, "Apache:mod_ssl:Error: Pass phrase empty (needs to be at least 1 character).\n"); else break; } } /* * Filter program */ else if (sc->server->pphrase_dialog_type == SSL_PPTYPE_FILTER) { const char *cmd = sc->server->pphrase_dialog_path; const char **argv = apr_palloc(p, sizeof(char *) * 4); char *result; ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, "Init: Requesting pass phrase from dialog filter " "program (%s)", cmd); argv[0] = cmd; argv[1] = cpVHostID; argv[2] = cpAlgoType; argv[3] = NULL; result = ssl_util_readfilter(s, p, cmd, argv); apr_cpystrn(buf, result, bufsize); len = strlen(buf); } /* * Ok, we now have the pass phrase, so give it back */ *cppPassPhraseCur = apr_pstrdup(p, buf); /* * And return it's length to OpenSSL... */ return (len);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -