/* Disconnect and some other clean up. */ int http_exit(http_t *client) { ASSERT(client); if (!client->initialized) return 0; client->initialized = 0; if (client->ssl_enabled) ssl_exit(client); return tcp_exit(&client->tcp); }
int main(int argc, char *argv[]) { int c, rc = 0, restart; struct option opt[] = { { "once", 0, 0, '1' }, { "continue-on-error", 0, 0, 'c' }, { "exec", 1, 0, 'e' }, { "config", 1, 0, 'f' }, { "iface", 1, 0, 'i' }, { "loglevel", 1, 0, 'l' }, { "help", 0, 0, 'h' }, { "foreground", 0, 0, 'n' }, { "pidfile", 1, 0, 100 }, { "drop-privs", 1, 0, 'p' }, { "syslog", 0, 0, 's' }, { "startup-delay", 1, 0, 't' }, { "version", 0, 0, 'v' }, { NULL, 0, 0, 0 } }; ddns_t *ctx = NULL; while ((c = getopt_long(argc, argv, "1ce:f:h?i:l:np:st:v", opt, NULL)) != EOF) { switch (c) { case '1': /* --once */ once = 1; break; case 'c': /* --continue-on-error */ ignore_errors = 1; break; case 'e': /* --exec=CMD */ script_exec = strdup(optarg); break; case 'f': /* --config=FILE */ config = strdup(optarg); break; case 'i': /* --iface=IFNAME */ iface = strdup(optarg); break; case 'l': /* --loglevel=LEVEL */ loglevel = loglvl(optarg); if (-1 == loglevel) return usage(1); break; case 'n': /* --foreground */ background = 0; break; case 100: /* --pidfile=BASENAME */ pidfile_name = strdup(optarg); break; case 'p': /* --drop-privs=USER[:GROUP] */ parse_privs(optarg); break; case 's': /* --syslog */ use_syslog = 1; break; case 't': /* --startup-delay=SEC */ startup_delay = atoi(optarg); break; case 'v': puts(VERSION); return 0; case 'h': /* --help */ case ':': /* Missing parameter for option. */ case '?': /* Unknown option. */ default: return usage(0); } } if (background) { if (daemon(0, 0) < 0) { fprintf(stderr, "Failed daemonizing %s: %m\n", __progname); return RC_OS_FORK_FAILURE; } use_syslog = 1; } if (use_syslog) { openlog(NULL, LOG_PID, LOG_USER); setlogmask(LOG_UPTO(loglevel)); } if (drop_privs()) { logit(LOG_WARNING, "Failed dropping privileges: %s", strerror(errno)); return RC_OS_CHANGE_PERSONA_FAILURE; } /* "Hello!" Let user know we've started up OK */ logit(LOG_NOTICE, "%s", VERSION_STRING); if (!config) config = strdup(DEFAULT_CONFIG_FILE); /* Prepare SSL library, if enabled */ ssl_init(); do { restart = 0; rc = alloc_context(&ctx); if (rc != RC_OK) break; if (os_install_signal_handler(ctx)) return RC_OS_INSTALL_SIGHANDLER_FAILED; cfg = conf_parse_file(config, ctx); if (!cfg) { free_context(ctx); return RC_FILE_IO_MISSING_FILE; } rc = ddns_main_loop(ctx); if (rc == RC_RESTART) restart = 1; free_context(ctx); cfg_free(cfg); } while (restart); if (use_syslog) closelog(); free(config); ssl_exit(); return rc; }
int ssl_init(http_t *client, char *msg) { #ifndef ENABLE_SSL (void)client; (void)msg; return 0; #else int err, err_ssl, rc = 0; char buf[256]; const char *sn; X509 *cert; if (client->verbose > 1) logit(LOG_INFO, "%s, initiating HTTPS ...", msg); do { client->ssl_ctx = SSL_CTX_new(SSLv23_client_method()); if (!client->ssl_ctx) return RC_HTTPS_OUT_OF_MEMORY; #if defined(CONFIG_OPENSSL) /* POODLE, only allow TLSv1.x or later */ SSL_CTX_set_options(client->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION); #endif client->ssl = SSL_new(client->ssl_ctx); if (!client->ssl) { rc = RC_HTTPS_OUT_OF_MEMORY; break; } http_get_remote_name(client, &sn); if (set_server_name(client->ssl, sn)) { rc = RC_HTTPS_SNI_ERROR; break; } SSL_set_fd(client->ssl, client->tcp.ip.socket); err = SSL_connect(client->ssl); if (err <= 0) { err_ssl = SSL_get_error(client->ssl, err); logit(LOG_ERR, "SSL_connect %s! (err: %d)", "FAILED", err_ssl); rc = RC_HTTPS_FAILED_CONNECT; break; } if (client->verbose > 0) logit(LOG_INFO, "SSL connection using %s", SSL_get_cipher(client->ssl)); /* Get server's certificate (note: beware of dynamic allocation) - opt */ cert = SSL_get_peer_certificate(client->ssl); if (!cert) { logit(LOG_ERR, "SSL_get_peer_certificate %s!", "FAILED"); rc = RC_HTTPS_FAILED_GETTING_CERT; break; } /* Logging some cert details. Please note: X509_NAME_oneline doesn't work when giving NULL instead of a buffer. */ buf[0] = 0; X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); if (client->verbose > 1) logit(LOG_INFO, "SSL server cert subject: %s", buf); buf[0] = 0; X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf)); if (client->verbose > 1) logit(LOG_INFO, "SSL server cert issuer: %s", buf); /* We could do all sorts of certificate verification stuff here before deallocating the certificate. */ X509_free(cert); } while (0); if (rc) { ssl_exit(client); return rc; } return 0; #endif }