Skip to content

Instantly share code, notes, and snippets.

@jedisct1
Created December 20, 2011 17:13
Show Gist options
  • Save jedisct1/1502360 to your computer and use it in GitHub Desktop.
Save jedisct1/1502360 to your computer and use it in GitHub Desktop.
Get Unbound status, for @digdns
#define UNBOUND_CONTROL_VERSION 1
#define UNBOUND_ETC_DIR "/var/unbound/etc"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
static int
contact_server(const char *svr, const char *port)
{
struct addrinfo *ai, hints;
int fd;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_NUMERICSERV;
if (getaddrinfo(svr, port, &hints, &ai) != 0) {
return -1;
}
fd = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP);
if (fd == -1) {
freeaddrinfo(ai);
return -1;
}
if (connect(fd, (struct sockaddr *) ai->ai_addr, ai->ai_addrlen) < 0) {
freeaddrinfo(ai);
return -1;
}
freeaddrinfo(ai);
return fd;
}
static SSL*
setup_ssl(SSL_CTX* ctx, int fd)
{
SSL *ssl;
X509 *x;
int r;
ssl = SSL_new(ctx);
if (!ssl) {
return NULL;
}
SSL_set_connect_state(ssl);
(void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
if (!SSL_set_fd(ssl, fd)) {
return NULL;
}
for(;;) {
ERR_clear_error();
if((r=SSL_do_handshake(ssl)) == 1) {
break;
}
r = SSL_get_error(ssl, r);
if (r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE) {
return NULL;
}
}
if(SSL_get_verify_result(ssl) != X509_V_OK) {
return NULL;
}
x = SSL_get_peer_certificate(ssl);
if (!x) {
return NULL;
}
X509_free(x);
return ssl;
}
static int
go_cmd(SSL *ssl, int argc, char *argv[])
{
char buf[1024];
const char *space = " ";
const char *newline = "\n";
char pre[10];
int was_error = 0, first_line = 1;
int r, i;
snprintf(pre, sizeof(pre), "UBCT%d ", UNBOUND_CONTROL_VERSION);
if (SSL_write(ssl, pre, (int)strlen(pre)) <= 0) {
return -1;
}
for (i=0; i<argc; i++) {
if (SSL_write(ssl, space, (int)strlen(space)) <= 0) {
return -1;
}
if (SSL_write(ssl, argv[i], (int)strlen(argv[i])) <= 0) {
return -1;
}
}
if (SSL_write(ssl, newline, (int)strlen(newline)) <= 0) {
return -1;
}
for (;;) {
ERR_clear_error();
if((r = SSL_read(ssl, buf, (int)sizeof(buf)-1)) <= 0) {
if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) {
break;
}
return -1;
}
buf[r] = 0;
printf("%s", buf);
if (first_line && strncmp(buf, "error", 5) == 0) {
was_error = 1;
}
first_line = 0;
}
return was_error;
}
static int
go(const char *svr, const char *port)
{
const char *s_cert = UNBOUND_ETC_DIR "/unbound_server.pem";
const char *c_key = UNBOUND_ETC_DIR "/unbound_control.key";
const char *c_cert = UNBOUND_ETC_DIR "/unbound_control.pem";
SSL_CTX *ctx;
SSL *ssl;
int fd;
int ret = 0;
ctx = SSL_CTX_new(SSLv23_client_method());
if (!ctx) {
if(!(SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)) {
SSL_CTX_free(ctx);
return -1;
}
}
if (!SSL_CTX_use_certificate_file(ctx,c_cert,SSL_FILETYPE_PEM) ||
!SSL_CTX_use_PrivateKey_file(ctx,c_key,SSL_FILETYPE_PEM) ||
!SSL_CTX_check_private_key(ctx)) {
SSL_CTX_free(ctx);
return -1;
}
if (SSL_CTX_load_verify_locations(ctx, s_cert, NULL) != 1) {
SSL_CTX_free(ctx);
return -1;
}
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
if ((fd = contact_server(svr, port)) == -1) {
SSL_CTX_free(ctx);
return -1;
}
if ((ssl = setup_ssl(ctx, fd)) == NULL) {
SSL_CTX_free(ctx);
return -1;
}
ret = go_cmd(ssl, 1, (char *[]) { "stats", NULL });
SSL_free(ssl);
close(fd);
SSL_CTX_free(ctx);
return ret;
}
static void
init(void)
{
ERR_load_crypto_strings();
ERR_load_SSL_strings();
OpenSSL_add_all_algorithms();
(void) SSL_library_init();
if (!RAND_status()) {
unsigned char buf[256];
unsigned int v, seed=(unsigned)time(NULL) ^ (unsigned)getpid();
size_t i;
for(i = 0; i < 256 / sizeof v; i++) {
memmove(buf + i * sizeof v, &v, sizeof v);
v = v * seed + (unsigned int) i;
}
RAND_seed(buf, 256);
}
}
int
main(void)
{
init();
go("127.0.0.1", "8953");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment