Commit 2129f5dd authored by ale's avatar ale

move buffer-management code to its own module, with tests; fix memory corruption bug in quote()

parent 54b47431
*.in
aclocal.m4
autom4te.cache
compile
config.guess
config.sub
configure
......@@ -26,5 +27,7 @@ libtool
stamp-*
Makefile
auth_client_test
cbuf_test
test-driver
test-suite.log
.dirstamp
......@@ -8,7 +8,8 @@ pam_LTLIBRARIES = pam_authclient.la
noinst_LIBRARIES = libgtest.a
libauthclient_la_SOURCES = \
auth_client.c auth_client.h
auth_client.c auth_client.h \
cbuf.c cbuf.h
libauthclient_la_includedir = $(includedir)/authclient
libauthclient_la_include_HEADERS = auth_client.h
......@@ -18,7 +19,8 @@ pam_authclient_la_LDFLAGS = -module
pam_authclient_la_LIBADD = libauthclient.la
check_PROGRAMS = \
auth_client_test
auth_client_test \
cbuf_test
TESTS = $(check_PROGRAMS)
......@@ -26,6 +28,9 @@ auth_client_test_CPPFLAGS = $(GTEST_CPPFLAGS)
auth_client_test_LDADD = libauthclient.la libgtest.a
auth_client_test_SOURCES = auth_client_test.cc
cbuf_test_CPPFLAGS = $(GTEST_CPPFLAGS)
cbuf_test_LDADD = libauthclient.la libgtest.a
cbuf_test_SOURCES = cbuf_test.cc
# GTest sources.
......
......@@ -9,6 +9,7 @@
#include <sys/stat.h>
#include <curl/curl.h>
#include "auth_client.h"
#include "cbuf.h"
#define CURL_CHECK(x) { \
int _err = (x); if (_err != CURLE_OK) { return auth_client_err_from_curl(_err); } \
......@@ -106,44 +107,6 @@ const char *auth_client_strerror(int err) {
}
}
/*
* A dynamically sized memory buffer that can be appended to, and will
* grow accordingly. It is optimized to perform well for a specific
* size (the initial allocation).
*/
struct cbuf {
char *buf;
size_t alloc, size;
};
static void cbuf_init(struct cbuf *cbuf, size_t alloc) {
cbuf->buf = (char *)malloc(alloc);
cbuf->alloc = alloc;
cbuf->size = 0;
}
static void cbuf_free(struct cbuf *cbuf) {
free(cbuf->buf);
}
static void cbuf_append(struct cbuf *cbuf, void *data, size_t size) {
// Resize if necessary.
size_t required_alloc = cbuf->size + size + 1;
if (required_alloc > cbuf->alloc) {
size_t new_alloc = cbuf->alloc;
while (new_alloc < required_alloc) {
new_alloc *= 2;
}
cbuf->buf = (char *)realloc(cbuf->buf, new_alloc);
cbuf->alloc = new_alloc;
}
// Append data to the buffer.
memcpy(cbuf->buf + cbuf->size, data, size);
cbuf->size += size;
cbuf->buf[cbuf->size] = '\0';
}
static char *quote(const char *s) {
char *out = (char *)malloc(strlen(s) * 3 + 1), *optr;
for (optr = out; *s; s++) {
......@@ -165,6 +128,7 @@ static char *quote(const char *s) {
*optr++ = *s;
}
}
*optr = '\0';
return out;
}
......@@ -177,14 +141,13 @@ static size_t responsebuf_callback(void *contents, size_t size, size_t nmemb, vo
}
static void post_field_add(struct cbuf *form_data, const char *key, const char *value) {
char *quoted_key = quote(key), *quoted_value = quote(value);
char *quoted_value = quote(value);
if (form_data->size != 0) {
cbuf_append(form_data, "&", 1);
}
cbuf_append(form_data, quoted_key, strlen(quoted_key));
cbuf_append(form_data, key, strlen(key));
cbuf_append(form_data, "=", 1);
cbuf_append(form_data, quoted_value, strlen(quoted_value));
free(quoted_key);
free(quoted_value);
}
......@@ -217,6 +180,7 @@ int auth_client_authenticate(auth_client_t ac,
post_field_add(&form, "shard", shard);
}
curl_easy_setopt(ac->c, CURLOPT_POSTFIELDS, form.buf);
curl_easy_setopt(ac->c, CURLOPT_POSTFIELDSIZE, form.size);
// Set request headers.
curl_slist_append(headers, "Content-Type: application/x-form-www-urlencoded");
......
......@@ -8,8 +8,8 @@ extern "C" {
static const char *server = NULL;
static const char *ssl_ca = "../authserv/test/testca/ca.pem";
static const char *ssl_cert = "../authserv/test/testca/certs/client.pem";
static const char *ssl_ca = "../authserv/test/testca/public/ca.pem";
static const char *ssl_cert = "../authserv/test/testca/public/certs/client.pem";
static const char *ssl_key = "../authserv/test/testca/private/client.key";
static const char *ssl_bad_ca = "../authserv/test/testca-bad/ca.pem";
static const char *ssl_bad_cert = "../authserv/test/testca-bad/certs/client.pem";
......@@ -59,6 +59,21 @@ TEST_F(AuthClientTest, AuthOK) {
<< ", server=" << server;
}
TEST_F(AuthClientTest, ManyAuthOK) {
int result;
for (int i = 0; i < 3; i++) {
result = auth_client_set_certificate(ac, ssl_ca, ssl_cert, ssl_key);
EXPECT_EQ(AC_OK, result) << "set_certificate() error: " << auth_client_strerror(result);
result = auth_client_authenticate(ac, "user", "pass", NULL, "127.0.0.1", NULL);
EXPECT_EQ(AC_OK, result) << "authenticate() error: " << auth_client_strerror(result)
<< ", server=" << server;
}
}
TEST_F(AuthClientTest, AuthFail) {
int result;
......
#include <stdlib.h>
#include <memory.h>
#include "cbuf.h"
void cbuf_init(struct cbuf *cbuf, size_t alloc) {
cbuf->buf = (char *)malloc(1);
cbuf->buf[0] = '\0';
cbuf->alloc = cbuf->size = 0;
}
void cbuf_free(struct cbuf *cbuf) {
free(cbuf->buf);
}
void cbuf_append(struct cbuf *cbuf, const char *data, size_t size) {
size_t new_alloc = cbuf->alloc + size;
cbuf->buf = (char *)realloc(cbuf->buf, new_alloc + 1);
memcpy(cbuf->buf + cbuf->size, data, size);
cbuf->alloc = cbuf->size = new_alloc;
cbuf->buf[cbuf->size] = '\0';
}
#ifndef __libauthclient_cbuf_h
#define __libauthclient_cbuf_h 1
#include <sys/types.h>
/*
* A dynamically sized memory buffer that can be appended to, and will
* grow accordingly. It is optimized to perform well for a specific
* size (the initial allocation).
*/
struct cbuf {
char *buf;
size_t alloc, size;
};
void cbuf_init(struct cbuf *cbuf, size_t alloc);
void cbuf_free(struct cbuf *cbuf);
void cbuf_append(struct cbuf *cbuf, const char *data, size_t size);
#endif
// Tests for cbuf.c.
#include <stdlib.h>
#include <string>
#include "gtest/gtest.h"
extern "C" {
#include "cbuf.h"
}
TEST(Cbuf, Append) {
struct cbuf c;
cbuf_init(&c, 0);
cbuf_append(&c, "hello, ", 7);
cbuf_append(&c, "world", 5);
std::string a(c.buf);
EXPECT_EQ("hello, world", a);
cbuf_free(&c);
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
......@@ -2,7 +2,7 @@ AC_INIT([libauthclient], [0.1], [info@autistici.org])
AC_CONFIG_SRCDIR([auth_client.h])
dnl AC_LANG(C)
AM_INIT_AUTOMAKE([foreign])
AM_INIT_AUTOMAKE([foreign subdir-objects])
AC_CONFIG_HEADERS(config.h)
AC_CONFIG_MACRO_DIR([m4])
AC_DISABLE_STATIC
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment