Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add ykclient_set_client_b64. Fix mem leaks. Fix multiple request resp…

…onse problem.
  • Loading branch information...
commit 28b847aff8bec4520653aa1fbf48adf3efdb77c4 1 parent d708bee
@jas4711 jas4711 authored
View
3  Makefile.am
@@ -38,7 +38,8 @@ libykclient_la_SOURCES = ykclient.h ykclient.c
libykclient_la_SOURCES += rfc4634/sha.h rfc4634/sha-private.h \
rfc4634/hmac.c rfc4634/sha1.c rfc4634/usha.c \
rfc4634/sha224-256.c rfc4634/sha384-512.c
-libykclient_la_SOURCES += b64/cencode.h b64/cencode.c
+libykclient_la_SOURCES += b64/cencode.h b64/cencode.c b64/cdecode.h \
+ b64/cdecode.c
libykclient_la_LIBADD = @LIBCURL@
libykclient_la_LDFLAGS = -no-undefined \
-export-symbols-regex '^ykclient_.*' \
View
6 NEWS
@@ -2,6 +2,12 @@ Yubikey-c-client NEWS -- History of user-visible changes. -*- outline -*-
* Version 2.3 (unreleased)
+** Add new API ykclient_set_client_b64 to set client key in b64 format.
+
+** Fix memory leaks.
+
+** Fix usage when sending multiple requests.
+
* Version 2.2 (released 2009-03-31)
** Add new API ykclient_set_client_hex to set client key in hex format.
View
87 b64/cdecode.c
@@ -0,0 +1,87 @@
+/*
+cdecoder.c - c source to a base64 decoding algorithm implementation
+
+This is part of the libb64 project, and has been placed in the public domain.
+For details, see http://sourceforge.net/projects/libb64
+*/
+
+#include <b64/cdecode.h>
+
+int base64_decode_value(char value_in)
+{
+ static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};
+ static const char decoding_size = sizeof(decoding);
+ value_in -= 43;
+ if (value_in < 0 || value_in > decoding_size) return -1;
+ return decoding[(int)value_in];
+}
+
+void base64_init_decodestate(base64_decodestate* state_in)
+{
+ state_in->step = step_a;
+ state_in->plainchar = 0;
+}
+
+int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in)
+{
+ const char* codechar = code_in;
+ char* plainchar = plaintext_out;
+ char fragment;
+
+ *plainchar = state_in->plainchar;
+
+ switch (state_in->step)
+ {
+ while (1)
+ {
+ case step_a:
+ do {
+ if (codechar == code_in+length_in)
+ {
+ state_in->step = step_a;
+ state_in->plainchar = *plainchar;
+ return plainchar - plaintext_out;
+ }
+ fragment = (char)base64_decode_value(*codechar++);
+ } while (fragment < 0);
+ *plainchar = (fragment & 0x03f) << 2;
+ case step_b:
+ do {
+ if (codechar == code_in+length_in)
+ {
+ state_in->step = step_b;
+ state_in->plainchar = *plainchar;
+ return plainchar - plaintext_out;
+ }
+ fragment = (char)base64_decode_value(*codechar++);
+ } while (fragment < 0);
+ *plainchar++ |= (fragment & 0x030) >> 4;
+ *plainchar = (fragment & 0x00f) << 4;
+ case step_c:
+ do {
+ if (codechar == code_in+length_in)
+ {
+ state_in->step = step_c;
+ state_in->plainchar = *plainchar;
+ return plainchar - plaintext_out;
+ }
+ fragment = (char)base64_decode_value(*codechar++);
+ } while (fragment < 0);
+ *plainchar++ |= (fragment & 0x03c) >> 2;
+ *plainchar = (fragment & 0x003) << 6;
+ case step_d:
+ do {
+ if (codechar == code_in+length_in)
+ {
+ state_in->step = step_d;
+ state_in->plainchar = *plainchar;
+ return plainchar - plaintext_out;
+ }
+ fragment = (char)base64_decode_value(*codechar++);
+ } while (fragment < 0);
+ *plainchar++ |= (fragment & 0x03f);
+ }
+ }
+ /* control should not reach here */
+ return plainchar - plaintext_out;
+}
View
28 b64/cdecode.h
@@ -0,0 +1,28 @@
+/*
+cdecode.h - c header for a base64 decoding algorithm
+
+This is part of the libb64 project, and has been placed in the public domain.
+For details, see http://sourceforge.net/projects/libb64
+*/
+
+#ifndef BASE64_CDECODE_H
+#define BASE64_CDECODE_H
+
+typedef enum
+{
+ step_a, step_b, step_c, step_d
+} base64_decodestep;
+
+typedef struct
+{
+ base64_decodestep step;
+ char plainchar;
+} base64_decodestate;
+
+void base64_init_decodestate(base64_decodestate* state_in);
+
+int base64_decode_value(char value_in);
+
+int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in);
+
+#endif /* BASE64_CDECODE_H */
View
44 selftest.c
@@ -42,6 +42,7 @@ main (void)
0x1f, 0x7d, 0xae, 0xfa, 0xbc, 0x77, 0xa4, 0x59, 0xd4, 0x33
};
char *client_hexkey = "a0155b36dec865e859191f7daefabc77a459d433";
+ char *client_b64key = "oBVbNt7IZehZGR99rvq8d6RZ1DM=";
ykclient_t *ykc;
int ret;
@@ -66,6 +67,14 @@ main (void)
if (ret != YKCLIENT_REPLAYED_OTP)
return 1;
+ ykclient_set_client (ykc, client_id, 10, client_key);
+
+ ret = ykclient_request (ykc, "dteffujehknhfjbrjnlnldnhcujvddbikngjrtgh");
+ printf ("ykclient_request (%d): %s\n", ret, ykclient_strerror (ret));
+ printf ("used url: %s\n", ykclient_get_last_url (ykc));
+ if (ret != YKCLIENT_BAD_SIGNATURE)
+ return 1;
+
ret = ykclient_set_client_hex (ykc, client_id, "a");
printf ("ykclient_set_client_hex (%d): %s\n", ret, ykclient_strerror (ret));
if (ret != YKCLIENT_HEX_DECODE_ERROR)
@@ -87,6 +96,39 @@ main (void)
if (ret != YKCLIENT_REPLAYED_OTP)
return 1;
+ ret = ykclient_set_client_hex (ykc, client_id, "deadbeef");
+ printf ("ykclient_set_client_hex (%d): %s\n", ret, ykclient_strerror (ret));
+ if (ret != YKCLIENT_OK)
+ return 1;
+
+ ret = ykclient_request (ykc, "dteffujehknhfjbrjnlnldnhcujvddbikngjrtgh");
+ printf ("ykclient_request (%d): %s\n", ret, ykclient_strerror (ret));
+ printf ("used url: %s\n", ykclient_get_last_url (ykc));
+ if (ret != YKCLIENT_BAD_SIGNATURE)
+ return 1;
+
+ ret = ykclient_set_client_b64 (ykc, client_id, "deadbeef");
+ printf ("ykclient_set_client_b64 (%d): %s\n", ret, ykclient_strerror (ret));
+ if (ret != YKCLIENT_OK)
+ return 1;
+
+ ret = ykclient_request (ykc, "dteffujehknhfjbrjnlnldnhcujvddbikngjrtgh");
+ printf ("ykclient_request (%d): %s\n", ret, ykclient_strerror (ret));
+ printf ("used url: %s\n", ykclient_get_last_url (ykc));
+ if (ret != YKCLIENT_BAD_SIGNATURE)
+ return 1;
+
+ ret = ykclient_set_client_b64 (ykc, client_id, client_b64key);
+ printf ("ykclient_set_client_b64 (%d): %s\n", ret, ykclient_strerror (ret));
+ if (ret != YKCLIENT_OK)
+ return 1;
+
+ ret = ykclient_request (ykc, "dteffujehknhfjbrjnlnldnhcujvddbikngjrtgh");
+ printf ("ykclient_request (%d): %s\n", ret, ykclient_strerror (ret));
+ printf ("used url: %s\n", ykclient_get_last_url (ykc));
+ if (ret != YKCLIENT_REPLAYED_OTP)
+ return 1;
+
/* Same URL used by library, somewhat silly but still verifies the
code path. */
ykclient_set_url_template
@@ -103,5 +145,7 @@ main (void)
printf ("strerror(0): %s\n", ykclient_strerror (0));
printf ("strerror(BAD_OTP): %s\n", ykclient_strerror (YKCLIENT_BAD_OTP));
+ printf ("All tests passed\n");
+
return 0;
}
View
3  simple.mk
@@ -38,7 +38,8 @@ PROGRAMS = ykclient selftest
all: $(PROGRAMS)
OBJECTS = ykclient.o rfc4634/hmac.o rfc4634/sha1.o rfc4634/usha.o \
- rfc4634/sha224-256.o rfc4634/sha384-512.o b64/cencode.o
+ rfc4634/sha224-256.o rfc4634/sha384-512.o b64/cencode.o \
+ b64/cdecode.o
$(PROGRAMS): $(OBJECTS)
View
52 ykclient.c
@@ -39,14 +39,9 @@
#include <curl/curl.h>
-#ifdef DEBUG
-# define D(x) do { \
- printf ("debug: %s:%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \
- printf x; \
- } while (0)
-#else
-# define D(x) /* nothing */
-#endif
+#include "rfc4634/sha.h"
+#include "b64/cencode.h"
+#include "b64/cdecode.h"
struct ykclient_st
{
@@ -140,6 +135,7 @@ ykclient_set_client_hex (ykclient_t *ykc,
bin_len = key_len / 2;
+ free (ykc->key_buf);
ykc->key_buf = malloc (bin_len);
if (!ykc->key_buf)
return YKCLIENT_OUT_OF_MEMORY;
@@ -151,6 +147,7 @@ ykclient_set_client_hex (ykclient_t *ykc,
if (sscanf (&key[2*i], "%02x", &tmp) != 1)
{
free (ykc->key_buf);
+ ykc->key_buf = NULL;
return YKCLIENT_HEX_DECODE_ERROR;
}
@@ -163,6 +160,33 @@ ykclient_set_client_hex (ykclient_t *ykc,
return YKCLIENT_OK;
}
+int
+ykclient_set_client_b64 (ykclient_t *ykc,
+ unsigned int client_id,
+ const char *key)
+{
+ size_t key_len;
+ base64_decodestate b64;
+
+ ykc->client_id = client_id;
+
+ if (key == NULL)
+ return YKCLIENT_OK;
+
+ key_len = strlen (key);
+
+ free (ykc->key_buf);
+ ykc->key_buf = malloc (key_len + 1);
+ if (!ykc->key_buf)
+ return YKCLIENT_OUT_OF_MEMORY;
+
+ base64_init_decodestate(&b64);
+ ykc->keylen = base64_decode_block(key, key_len, ykc->key_buf, &b64);
+ ykc->key = ykc->key_buf;
+
+ return YKCLIENT_OK;
+}
+
void
ykclient_set_url_template (ykclient_t *ykc,
const char *url_template)
@@ -288,9 +312,6 @@ curl_callback (void *ptr, size_t size, size_t nmemb, void *data)
return realsize;
}
-#include "rfc4634/sha.h"
-#include "b64/cencode.h"
-
int
ykclient_request (ykclient_t *ykc,
const char *yubikey)
@@ -303,6 +324,10 @@ ykclient_request (ykclient_t *ykc,
if (!url_template)
url_template = "http://api.yubico.com/wsapi/verify?id=%d&otp=%s";
+ free (ykc->curl_chunk);
+ ykc->curl_chunk_size = 0;
+ ykc->curl_chunk = NULL;
+
{
size_t len = strlen (url_template) + strlen (yubikey) + 20;
size_t wrote;
@@ -395,9 +420,6 @@ ykclient_request (ykclient_t *ykc,
goto done;
}
- D (("server response (%d): %.*s", ykc->curl_chunk_size,
- ykc->curl_chunk_size, ykc->curl_chunk));
-
status = strstr (ykc->curl_chunk, "status=");
if (!status)
{
@@ -409,8 +431,6 @@ ykclient_request (ykclient_t *ykc,
|| status[strlen (status) - 1] == '\n')
status[strlen (status) - 1] = '\0';
- D (("parsed status (%d): %s\n", strlen (status), status));
-
if (strcmp (status, "status=OK") == 0)
{
out = YKCLIENT_OK;
View
4 ykclient.h
@@ -71,6 +71,10 @@ extern int ykclient_set_client_hex (ykclient_t *ykc,
unsigned int client_id,
const char *key);
+extern int ykclient_set_client_b64 (ykclient_t *ykc,
+ unsigned int client_id,
+ const char *key);
+
extern void ykclient_set_url_template (ykclient_t *ykc,
const char *url_template);
Please sign in to comment.
Something went wrong with that request. Please try again.