static int sha1(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) { *buf = '\0'; if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "Syntax: SHA1(<data>) - missing argument!\n"); return -1; } if (len >= 41) ast_sha1_hash(buf, data); else { ast_log(LOG_ERROR, "Insufficient space to produce SHA1 hash result (%d < 41)\n", (int) len); } return 0; }
void ast_tcptls_server_start(struct ast_tcptls_session_args *desc) { int flags; int x = 1; int tls_changed = 0; if (desc->tls_cfg) { char hash[41]; char *str = NULL; struct stat st; /* Store the hashes of the TLS certificate etc. */ if (stat(desc->tls_cfg->certfile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->certfile))) { memset(hash, 0, 41); } else { ast_sha1_hash(hash, str); } ast_free(str); str = NULL; memcpy(desc->tls_cfg->certhash, hash, 41); if (stat(desc->tls_cfg->pvtfile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->pvtfile))) { memset(hash, 0, 41); } else { ast_sha1_hash(hash, str); } ast_free(str); str = NULL; memcpy(desc->tls_cfg->pvthash, hash, 41); if (stat(desc->tls_cfg->cafile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->cafile))) { memset(hash, 0, 41); } else { ast_sha1_hash(hash, str); } ast_free(str); str = NULL; memcpy(desc->tls_cfg->cahash, hash, 41); /* Check whether TLS configuration has changed */ if (!desc->old_tls_cfg) { /* No previous configuration */ tls_changed = 1; desc->old_tls_cfg = ast_calloc(1, sizeof(*desc->old_tls_cfg)); } else if (memcmp(desc->tls_cfg->certhash, desc->old_tls_cfg->certhash, 41)) { tls_changed = 1; } else if (memcmp(desc->tls_cfg->pvthash, desc->old_tls_cfg->pvthash, 41)) { tls_changed = 1; } else if (strcmp(desc->tls_cfg->cipher, desc->old_tls_cfg->cipher)) { tls_changed = 1; } else if (memcmp(desc->tls_cfg->cahash, desc->old_tls_cfg->cahash, 41)) { tls_changed = 1; } else if (strcmp(desc->tls_cfg->capath, desc->old_tls_cfg->capath)) { tls_changed = 1; } else if (memcmp(&desc->tls_cfg->flags, &desc->old_tls_cfg->flags, sizeof(desc->tls_cfg->flags))) { tls_changed = 1; } if (tls_changed) { ast_debug(1, "Changed parameters for %s found\n", desc->name); } } /* Do nothing if nothing has changed */ if (!tls_changed && !ast_sockaddr_cmp(&desc->old_address, &desc->local_address)) { ast_debug(1, "Nothing changed in %s\n", desc->name); return; } /* If we return early, there is no one listening */ ast_sockaddr_setnull(&desc->old_address); /* Shutdown a running server if there is one */ if (desc->master != AST_PTHREADT_NULL) { pthread_cancel(desc->master); pthread_kill(desc->master, SIGURG); pthread_join(desc->master, NULL); } if (desc->accept_fd != -1) { close(desc->accept_fd); } /* If there's no new server, stop here */ if (ast_sockaddr_isnull(&desc->local_address)) { ast_debug(2, "Server disabled: %s\n", desc->name); return; } desc->accept_fd = socket(ast_sockaddr_is_ipv6(&desc->local_address) ? AF_INET6 : AF_INET, SOCK_STREAM, 0); if (desc->accept_fd < 0) { ast_log(LOG_ERROR, "Unable to allocate socket for %s: %s\n", desc->name, strerror(errno)); return; } setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); if (ast_bind(desc->accept_fd, &desc->local_address)) { ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n", desc->name, ast_sockaddr_stringify(&desc->local_address), strerror(errno)); goto error; } if (listen(desc->accept_fd, 10)) { ast_log(LOG_ERROR, "Unable to listen for %s!\n", desc->name); goto error; } flags = fcntl(desc->accept_fd, F_GETFL); fcntl(desc->accept_fd, F_SETFL, flags | O_NONBLOCK); if (ast_pthread_create_background(&desc->master, NULL, desc->accept_fn, desc)) { ast_log(LOG_ERROR, "Unable to launch thread for %s on %s: %s\n", desc->name, ast_sockaddr_stringify(&desc->local_address), strerror(errno)); goto error; } /* Set current info */ ast_sockaddr_copy(&desc->old_address, &desc->local_address); if (desc->old_tls_cfg) { ast_free(desc->old_tls_cfg->certfile); ast_free(desc->old_tls_cfg->pvtfile); ast_free(desc->old_tls_cfg->cipher); ast_free(desc->old_tls_cfg->cafile); ast_free(desc->old_tls_cfg->capath); desc->old_tls_cfg->certfile = ast_strdup(desc->tls_cfg->certfile); desc->old_tls_cfg->pvtfile = ast_strdup(desc->tls_cfg->pvtfile); desc->old_tls_cfg->cipher = ast_strdup(desc->tls_cfg->cipher); desc->old_tls_cfg->cafile = ast_strdup(desc->tls_cfg->cafile); desc->old_tls_cfg->capath = ast_strdup(desc->tls_cfg->capath); memcpy(desc->old_tls_cfg->certhash, desc->tls_cfg->certhash, 41); memcpy(desc->old_tls_cfg->pvthash, desc->tls_cfg->pvthash, 41); memcpy(desc->old_tls_cfg->cahash, desc->tls_cfg->cahash, 41); memcpy(&desc->old_tls_cfg->flags, &desc->tls_cfg->flags, sizeof(desc->old_tls_cfg->flags)); } return; error: close(desc->accept_fd); desc->accept_fd = -1; }