#include "config.h" #include #ifdef HAVE_STRING_H #include #endif /* HAVE_STRING_H */ #ifdef HAVE_ERRNO_H #include #endif /* HAVE_ERRNO_H */ #ifndef NO_SSL #include #include #endif #include "common.h" #ifndef NO_SSL #include "dynassl.h" #endif #include "Config.h" #include "cmd.h" #include "bool.h" #include "parse.h" #include "util.h" /* ================================================================= */ #define DEFAULT_DENY_WAIT_TIME 3 #define DEFAULT_READ_TIMEOUT 0 #define DEFAULT_MAX_CONNECTION 100 #define DEFAULT_SPARE_SERVERS 1 /* ================================================================= */ const CMDLIST* in_word_set_cmdlist (register const char *str, register int len); const BOOLLIST* in_word_set_boollist (register const char *str, register int len); /* ================================================================= */ #ifndef NO_SSL /* ----------------------------------------------------------------- * =NAME= initSSL - prepare using SSLeay library =RETURN= FALSE : error TRUE : sucess * ----------------------------------------------------------------- */ int initSSL() { _SSLeay_add_ssl_algorithms(); _SSL_load_error_strings(); return TRUE; } int verify_depth = 10; int verify_error=X509_V_OK; int BjorbSSLVerifyCallback(int ok, X509_STORE_CTX *ctx) { char buf[256]; PUTERR(0, ("DEBUG: BjorbSSLVerifyCallback\n")); X509 *xs = X509_STORE_CTX_get_current_cert(ctx); int err = X509_STORE_CTX_get_error(ctx); int depth = X509_STORE_CTX_get_error_depth(ctx); if (log_level >= 2) { X509_NAME_oneline(X509_get_subject_name(xs),buf,256); PUTERR(2, ("BjorbSSLVerifyCallback: depth = %d, %s\n", depth, buf)); } if (!ok) { PUTERR(0, ("SSL verify error: error = %d: %s\n", err, X509_verify_cert_error_string(err))); if (verify_depth >= depth) { ok = 1; verify_error = X509_V_OK; } else { ok = 0; verify_error = X509_V_ERR_CERT_CHAIN_TOO_LONG; } } switch(ctx->error) { case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),buf,256); PUTERR(0, ("BjorbSSLVerifyCallback: issuer = %s\n", buf)); break; case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: #if 0 { FILE *fp = elogp->fp; PUTERR(0, ("BjorbSSLVerifyCallback: notBefore=")); ASN1_UTCTIME_print(BIO_fp,X509_get_notBefore(ctx->current_cert)); PUTERR(0, ("\n")); } #endif break; case X509_V_ERR_CERT_HAS_EXPIRED: case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: #if 0 { FILE *fp = elogp->fp; PUTERR(0, ("BjorbSSLVerifyCallback: notAfter=")); ASN1_UTCTIME_print(fp,X509_get_notAfter(ctx->current_cert)); PUTERR(0, ("\n")); } #endif break; } return(ok); } #endif /* !NO_SSL */ /* ----------------------------------------------------------------- */ void Config::debug() { Logger *old_elogp = ::elogp; ::elogp = elogp; PUTERR(0, ("============DEBUG OUTPUT============\n")); PUTERR(0, ("log_level = %d\n", log_level)); PUTERR(0, ("read_timeout = %d\n", read_timeout)); PUTERR(0, ("max_conncetion = %d\n", max_connection)); PUTERR(0, ("deny_wait = %d\n", deny_wait)); PUTERR(0, ("spare_servers = %d\n", spare_servers)); PUTERR(0, ("do_fork = %d\n", do_fork)); PUTERR(0, ("access_log = %s\n", access_log)); PUTERR(0, ("error_log = %s\n", error_log)); PUTERR(0, ("CA_cert_file = %s\n", CA_cert_file)); PUTERR(0, ("CA_cert_path = %s\n", CA_cert_path)); PUTERR(0, ("client_cert_file= %s\n", client_cert_file)); PUTERR(0, ("[accept]\n")); accept_port.debug(); PUTERR(0, ("[connect]\n")); connect_port.debug(); acl.debug(); PUTERR(0, ("====================================\n")); ::elogp = old_elogp; } void Config::setNext(Config *obj) { if (!next) { next = obj; obj->parent = this; } else { next->setNext(obj); } } int Config::init() { if (!parent) { /* initialize */ if (log_level < 0) log_level = 0; if (read_timeout < 0) read_timeout = DEFAULT_READ_TIMEOUT; if (max_connection < 0) max_connection = DEFAULT_MAX_CONNECTION; if (deny_wait < 0) deny_wait = DEFAULT_DENY_WAIT_TIME; if (spare_servers < 0) spare_servers = DEFAULT_SPARE_SERVERS; if (do_fork < 0) do_fork = (spare_servers > 0) ? FALSE : TRUE; } else { /* inherit */ if (log_level < 0) log_level = parent->log_level; if (read_timeout < 0) read_timeout = parent->read_timeout; if (max_connection < 0) max_connection = parent->max_connection; if (deny_wait < 0) deny_wait = parent->deny_wait; if (spare_servers < 0) spare_servers = parent->spare_servers; if (do_fork < 0) do_fork = parent->do_fork; acl.catACL(parent->acl.getACL()); #ifndef NO_SSL if (!*CA_cert_file) STRCPY(CA_cert_file , parent->CA_cert_file); if (!*CA_cert_path) STRCPY(CA_cert_path , parent->CA_cert_path); if (!*client_cert_file) STRCPY(client_cert_file, parent->client_cert_file); if (!CA_X509) CA_X509 = parent->CA_X509; if (!CA_RSA) CA_RSA = parent->CA_RSA; #endif /* !NO_SSL */ } if (do_fork == FALSE) max_connection = 1; if (max_connection == 1) do_fork = FALSE; if (*access_log) { if (!openAccessLog()) return FALSE; } else { if (!parent) { alogp = 0; } else { alogp = parent->alogp; } } if (*error_log) { if (!openErrorLog()) return FALSE; } else { if (!parent) { elogp = &stderrLog; } else { elogp = parent->elogp; } } return TRUE; } int Config::readFile(char *filename) { FILE *fp; int ret; fp = openSearch(filename, CONFIG_FILE_SEARCH_PATH, CONFIG_FILE_NAME); if (!fp) { if (filename) { PUTERR(0, ("Can't open config file `%s': %s\n", filename, strerror(errno))); } else { PUTERR(0, ("Can't open config file `%s' in path `%s' : %s\n", CONFIG_FILE_NAME, CONFIG_FILE_SEARCH_PATH, strerror(errno))); } return FALSE; } ret = parse(fp); fclose(fp); if (ret != 1) { PUTERR(0, ("Failed in reading a config file\n")); return FALSE; } return TRUE; } /* ----------------------------------------------------------------- * =NAME= Config::parse =RETURN= 0 : error 1 : end of file 2 : end of block * ----------------------------------------------------------------- */ int Config::parse(FILE *fp) { char s[LINEBUFSIZ]; char buf[LINEBUFSIZ]; char *p; int ret; const CMDLIST *clp; int data; int line = 0; char c; while (fgets(s, LINEBUFSIZ - 1, fp)) { line++; p = s; skipSpace(&p); c = *p; if (c < ' ' || c == '#') continue; getTokenStr(&p, buf, LINEBUFSIZ); clp = in_word_set_cmdlist(buf, strlen(buf)); if (clp) { skipSpace(&p); switch (clp->type) { case PARAM_NUM: getTokenInt(&p, &data); ret = clp->func(this, (int *)&data); break; case PARAM_ACL: case PARAM_PORTINFO: getTokenStrAll(&p, buf, LINEBUFSIZ); ret = clp->func(this, buf); break; case PARAM_READFILE: getTokenStr(&p, buf, LINEBUFSIZ); if (!checkOpenFileForRead(buf)) { fprintf(stderr, "line %d: Can't open file `%s' for read: %s\n", line, buf, strerror(errno)); return 0; } ret = clp->func(this, buf); break; case PARAM_STRING: getTokenStr(&p, buf, LINEBUFSIZ); ret = clp->func(this, buf); break; case PARAM_PARAM: getTokenStrAll(&p, buf, LINEBUFSIZ); ret = clp->func(this, buf); break; case PARAM_BOOL: { getTokenStr(&p, buf, LINEBUFSIZ); toLowerString(buf); const BOOLLIST *p = in_word_set_boollist(buf, strlen(buf)); if (p) { ret = clp->func(this, (int *)&p->value); } else { fprintf(stderr, "line %d: invalid parameter `%s'\n", line, buf); return 0; } } break; case PARAM_BLOCK: getTokenStr(&p, buf, LINEBUFSIZ); if (*buf == '{') { fprintf(stderr, "line %d: not found servicename after 'entry'\n", line); return 0; } skipSpace(&p); if (*p != '{') { fprintf(stderr, "line %d: not found '{' after `entry'.\n", line); return 0; } Config *obj = new Config(buf); setNext(obj); ret = obj->parse(fp); if (ret != 2) return 0; break; } if (!ret) return 0; } else { if (*buf == '}') return 2; fprintf(stderr, "line %d: unknown command `%s'\n", line, buf); } } return 1; } #ifdef NO_SSL int Config::makeCert(char *commonName, time_t days, int bits) { return 1; } #else /* !NO_SSL */ int Config::makeCert(char *commonName, time_t days, int bits) { PUTERR(1, ("Generating a %d bit RSA private key\n", bits)); EVP_PKEY *pkey = 0; const EVP_MD *digest = EVP_md5(); X509 *x509 = 0; X509_NAME *n = 0; X509_NAME_ENTRY *ne = 0; ASN1_UTCTIME *notBefore = 0; ASN1_UTCTIME *notAfter = 0; int ret = FALSE; int j; time_t t, tmax; char tbuf[40]; /* generate RSA key */ pkey = EVP_PKEY_new(); if (!pkey) { fprintf(stderr, "EVP_PKEY_new() error\n"); goto makeCert_end; } if (!EVP_PKEY_assign_RSA(pkey, _RSA_generate_key(bits,0x10001,0))) { fprintf(stderr, "EVP_PKEY_assign_RSA() erorr\n"); goto makeCert_end; } PUTERR(1, ("Key generation has done.\n")); /* */ n = X509_NAME_new(); if (!n) { fprintf(stderr, "X509_NAME_new() error\n"); goto makeCert_end; } j = ASN1_PRINTABLE_type((UCHAR *)commonName, -1); ne = X509_NAME_ENTRY_create_by_NID(0, NID_commonName, j, (UCHAR *)commonName, strlen(commonName)); if (!ne) { fprintf(stderr, "X509_NAME_ENTRY_create_by_NID() error\n"); goto makeCert_end; } if (!X509_NAME_add_entry(n, ne, X509_NAME_entry_count(n), 0)) { fprintf(stderr, "X509_NAME_add_entry() error\n"); goto makeCert_end; } t = time(0); tmax = t + (time_t)(60 * 60 * 24 * days); notBefore = ASN1_UTCTIME_set(0, t); notAfter = ASN1_UTCTIME_set(0, tmax); /* create x509 */ x509 = X509_new(); ASN1_INTEGER_set(X509_get_serialNumber(x509),0L); X509_set_issuer_name(x509, n); X509_set_notBefore(x509, notBefore); X509_set_notAfter(x509, notAfter); X509_set_subject_name(x509, n); X509_set_pubkey(x509, pkey); if (!X509_sign(x509,pkey,digest)) { fprintf(stderr, "X509_sign() error\n"); goto makeCert_end; } CA_X509 = x509; CA_RSA = X509_get_pubkey(x509)->pkey.rsa; ret = TRUE; PUTERR(1, ("Certificate available until %s was generated.\n", getTimeStr(&tmax, tbuf, 40))); makeCert_end: if (pkey) EVP_PKEY_free(pkey); if (n) X509_NAME_free(n); if (ne) X509_NAME_ENTRY_free(ne); if (notBefore) ASN1_UTCTIME_free(notBefore); if (notAfter) ASN1_UTCTIME_free(notAfter); return ret; } #endif /* !NO_SSL */