Skip to content

Commit 4a41960

Browse files
committed
* Fixed a huge bug- kerberos passwords are now url-encoded prior to being sent to the server.
* Added DEBUG explicitly to all compiled source * Created a functional test harness, albeit not testing kerberos, it tests the curl.* libraries and some minor kerberos loading functionality
1 parent 53b5dc7 commit 4a41960

File tree

5 files changed

+136
-14
lines changed

5 files changed

+136
-14
lines changed

common/curl.c

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
////////////////////////////////////////////////////////////////////////////////////
1919
////////////////////////////////////////////////////////////////////////////////////
2020

21+
char rfc3986[256] = {0};
22+
2123
static size_t
2224
WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
2325
{
@@ -38,7 +40,40 @@ WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
3840
return realsize;
3941
}
4042

43+
void init_urlencode(void)
44+
{
45+
int i;
46+
for (i = 0; i < 256; i++)
47+
{
48+
rfc3986[i] = isalnum(i)||i == '~'||i == '-'||i == '.'||i == '_' ? i : 0;
49+
}
50+
}
51+
52+
void urlencode(const char* src, char* encoded)
53+
{
54+
//syslog(LOG_DEBUG,"Got url escape request: %s",src);
55+
for (; *src; src++) {
56+
if (rfc3986[*src])
57+
{
58+
sprintf(encoded, "%c", rfc3986[*src]);
59+
//syslog(LOG_DEBUG,"std Here: %c: %s",*src,src);
60+
}
61+
else
62+
{
63+
sprintf(encoded, "%%%02X", *src);
64+
//syslog(LOG_DEBUG,"esc Here: %c: %s",*src,src);
65+
}
66+
while (*++encoded);
67+
}
68+
}
69+
70+
////////////////////////////////////////////////////////////////////////////////////
71+
72+
#ifdef DEBUG
73+
int __export queryUrl(const char* dest_url, struct MemoryStruct* chunk, int useInsecureSSL)
74+
#else
4175
int queryUrl(const char* dest_url, struct MemoryStruct* chunk, int useInsecureSSL)
76+
#endif
4277
{
4378
CURL *curl;
4479
CURLcode res;
@@ -48,8 +83,11 @@ int queryUrl(const char* dest_url, struct MemoryStruct* chunk, int useInsecureSS
4883

4984
curl = curl_easy_init();
5085
if(curl) {
51-
char* escaped_url = curl_easy_escape(curl, dest_url, 0);
52-
curl_easy_setopt(curl, CURLOPT_URL, escaped_url);
86+
//char* escaped_url = curl_easy_escape(curl, dest_url, 0);
87+
#ifdef DEBUG
88+
syslog(LOG_INFO, "pwncheck: queryUrl: DEBUG: destination url: %s",dest_url);
89+
#endif
90+
curl_easy_setopt(curl, CURLOPT_URL, dest_url);
5391

5492
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
5593
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)chunk);
@@ -68,7 +106,7 @@ int queryUrl(const char* dest_url, struct MemoryStruct* chunk, int useInsecureSS
68106
syslog(LOG_ERR, "pwncheck: queryUrl: curl_easy_perform() failed: %s", curl_easy_strerror(res));
69107

70108
/* always cleanup */
71-
curl_free(escaped_url);
109+
//curl_free(escaped_url);
72110
curl_easy_cleanup(curl);
73111
}
74112

common/curl.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,23 @@
77

88
#include <curl/curl.h> // curl
99

10+
#ifdef DEBUG
11+
#ifndef __export
12+
#define __export __attribute__((__visibility__("default")))
13+
#endif
14+
#endif
15+
1016
struct MemoryStruct {
1117
char *memory;
1218
size_t size;
1319
};
1420

21+
void init_urlencode(void);
22+
void urlencode(const char* src, char* encoded);
23+
1524
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp);
25+
#ifdef DEBUG
26+
int __export queryUrl(const char* dest_url, struct MemoryStruct* chunk, int useInsecureSSL);
27+
#else
1628
int queryUrl(const char* dest_url, struct MemoryStruct* chunk, int useInsecureSSL);
17-
29+
#endif

kerberos/build-debug.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
#cp /lib/security/pwncheck.so /usr/lib/x86_64-linux-gnu/krb5/plugins/pwqual/
77

88
gcc -g -shared -fPIC -fno-stack-protector -DDEBUG -c src/krb_password_pwncheck.c -lcurl -lcrypto -o bin/krb_password_pwncheck.o && \
9-
gcc -g -shared -fPIC -fno-stack-protector -c src/config.c -lcurl -lcrypto -o bin/config.o && \
10-
gcc -g -shared -fPIC -fno-stack-protector -c ../common/curl.c -lcurl -lcrypto -o bin/curl.o && \
9+
gcc -g -shared -fPIC -fno-stack-protector -DDEBUG -c src/config.c -lcurl -lcrypto -o bin/config.o && \
10+
gcc -g -shared -fPIC -fno-stack-protector -DDEBUG -c ../common/curl.c -lcurl -lcrypto -o bin/curl.o && \
1111
gcc -g -o bin/harness src/harness.c -ldl
1212
ld -g -x --shared -o bin/pwncheck.so bin/krb_password_pwncheck.o bin/config.o bin/curl.o -lefence -lcurl -lcrypto -lyaml
1313
cp bin/pwncheck.so /usr/lib/x86_64-linux-gnu/krb5/plugins/pwqual/

kerberos/src/harness.c

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,21 @@
77
#include <krb5/pwqual_plugin.h>
88
#include <stdlib.h>
99
#include <stdio.h>
10+
#include <string.h>
1011
#include <dlfcn.h>
12+
#include "../../common/curl.h"
13+
#include "../../common/constants.h"
1114

1215
#include <stddef.h>
1316

1417
/*
1518
krb5_error_code __export
1619
pwqual_pwncheck_initvt(krb5_context context, int maj_ver, int min_ver,
1720
krb5_plugin_vtable vtable)
21+
static krb5_error_code
22+
pwqual_pwncheck_check(krb5_context context, krb5_pwqual_moddata data,
23+
const char *passwd, const char *policy_name,
24+
krb5_principal princ, const char **languages)
1825
*/
1926

2027
#ifndef NULL
@@ -29,9 +36,12 @@ int main(int argc, char **argv) {
2936
void *handle;
3037
krb5_error_code (*initvt)(krb5_context context, int maj_ver, int min_ver, krb5_plugin_vtable vtable);
3138
krb5_error_code (*check)(krb5_context context, krb5_pwqual_moddata data, const char *passwd, const char *policy_name, krb5_principal princ, const char **languages);
39+
int (*queryUrl)(const char* dest_url, struct MemoryStruct* chunk, int useInsecureSSL);
40+
void (*init_urlencode)(void);
41+
void (*urlencode)(const char* src, char* encoded);
3242
char *error;
3343

34-
printf("Opening Dynamic Library...");
44+
printf("Opening Dynamic Library...\n");
3545
//handle = dlopen ("./pwncheck.so", RTLD_LAZY);
3646
//handle = dlopen (argv[1], RTLD_LAZY);
3747
handle = dlopen (argv[1], PLUGIN_DLOPEN_FLAGS);
@@ -50,8 +60,56 @@ int main(int argc, char **argv) {
5060
exit(1);
5161
}
5262
printf("Done\n");
63+
printf("Loading Dynamic Symbol (urlencode)...");
64+
urlencode = dlsym(handle, "urlencode");
65+
if ((error = dlerror()) != NULL) {
66+
fputs(error, stderr);
67+
printf("\n");
68+
exit(1);
69+
}
70+
printf("Done\n");
71+
printf("Loading Dynamic Symbol (init_urlencode)...");
72+
init_urlencode = dlsym(handle, "init_urlencode");
73+
if ((error = dlerror()) != NULL) {
74+
fputs(error, stderr);
75+
printf("\n");
76+
exit(1);
77+
}
78+
printf("Done\n");
79+
printf("Loading Dynamic Symbol (queryUrl)...");
80+
queryUrl = dlsym(handle, "queryUrl");
81+
if ((error = dlerror()) != NULL) {
82+
fputs(error, stderr);
83+
printf("\n");
84+
exit(1);
85+
}
86+
printf("Done\n");
87+
88+
(*init_urlencode)();
89+
struct MemoryStruct chunk;
90+
chunk.memory = malloc(1);
91+
chunk.size = 0;
92+
memset(chunk.memory,'\0',1);
93+
printf("Attempting to execute loaded symbol (function queryUrl)...\n");
94+
printf("\n");
95+
char filled_url[CURL_MAX_BUFLEN];
96+
char* user = "user";
97+
char* passwd = "this ia a sample . pass\' word ";
98+
char* url = "http://localhost:8000/checkpwd?u=%s&p=%s";
99+
char* escaped_user = (char*)malloc(strlen(user)*3+1); // up to 3 chars, e.g. ' ' => '%20' per original char, and end null
100+
char* escaped_passwd = (char*)malloc(strlen(passwd)*3+1); // up to 3 chars, e.g. ' ' => '%20' per original char, and end null
101+
(*urlencode)(user,escaped_user);
102+
(*urlencode)(passwd,escaped_passwd);
103+
int furllen = strlen(url)+strlen(escaped_user)+strlen(escaped_passwd);
104+
if (furllen > CURL_MAX_BUFLEN) furllen = CURL_MAX_BUFLEN;
105+
snprintf(filled_url, furllen, url, escaped_user, escaped_passwd);
106+
free(escaped_user);
107+
free(escaped_passwd);
108+
(*queryUrl)(filled_url,&chunk,1);
109+
printf("Function queryUrl execution done\n");
110+
53111

54-
112+
/*
55113
krb5_context context;
56114
//krb5_plugin_vtable vt;
57115
struct krb5_pwqual_vtable_st harness_vt = {NULL,NULL,NULL,NULL};
@@ -60,6 +118,7 @@ int main(int argc, char **argv) {
60118
const char* policy_name = "policy";
61119
krb5_principal princ = NULL; // {0,{7,"norealm"},NULL,5,0};
62120
char** langs = NULL;
121+
63122
printf("Attempting to execute loaded symbol (function initvt)...");
64123
printf("\n");
65124
(*initvt)(context, 2, 0, (struct krb5_plugin_vtable_st *)&harness_vt);
@@ -69,7 +128,7 @@ int main(int argc, char **argv) {
69128
printf("\n");
70129
(*check)(context, moddata, passwd, policy_name,princ, NULL);
71130
printf("\n");
72-
131+
*/
73132
printf("Closing the Dynamic Library handle...");
74133
dlclose(handle);
75134
printf("Done\n");

kerberos/src/krb_password_pwncheck.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
#include "../../common/curl.h"
2929
#include "../../common/constants.h"
3030

31+
// for encoding
32+
#include <stdio.h>
33+
#include <ctype.h>
3134

3235
// kerberos
3336

@@ -50,10 +53,13 @@
5053
////////////////////////////////////////////////////////////////////////////////////
5154
////////////////////////////////////////////////////////////////////////////////////
5255

53-
////////////////////////////////////////////////////////////////////////////////////
5456
// Perform the actual password quality check //
5557
////////////////////////////////////////////////////////////////////////////////////
56-
static krb5_error_code
58+
#ifdef DEBUG
59+
krb5_error_code extern __export
60+
#else
61+
static krb5_error_code
62+
#endif
5763
pwqual_pwncheck_check(krb5_context context, krb5_pwqual_moddata data,
5864
const char *passwd, const char *policy_name,
5965
krb5_principal princ, const char **languages)
@@ -97,13 +103,18 @@ pwqual_pwncheck_check(krb5_context context, krb5_pwqual_moddata data,
97103
url = config.url;
98104
}
99105

100-
101106

102107
char filled_url[CURL_MAX_BUFLEN];
103108
//int furllen = CURL_MAX_BUFLEN > strlen(url)+strlen(user)+strlen(passwd) ? CURL_MAX_BUFLEN : strlen(url)+strlen(user)+strlen(passwd);
104-
int furllen = strlen(url)+strlen(user)+strlen(passwd);
109+
char* escaped_user = (char*)malloc(strlen(user)*3+1); // up to 3 chars, e.g. ' ' => '%20' per original char, and end null
110+
char* escaped_passwd = (char*)malloc(strlen(passwd)*3+1); // up to 3 chars, e.g. ' ' => '%20' per original char, and end null
111+
urlencode(user,escaped_user);
112+
urlencode(passwd,escaped_passwd);
113+
int furllen = strlen(url)+strlen(escaped_user)+strlen(escaped_passwd);
105114
if (furllen > CURL_MAX_BUFLEN) furllen = CURL_MAX_BUFLEN;
106-
snprintf(filled_url, furllen, url, user, passwd);
115+
snprintf(filled_url, furllen, url, escaped_user, escaped_passwd);
116+
free(escaped_user);
117+
free(escaped_passwd);
107118
#ifdef DEBUG
108119
syslog(LOG_DEBUG, "pwncheck: check: user:%s password:%s",user,passwd);
109120
syslog(LOG_DEBUG, "pwncheck: check: Created Filling URL: %s", filled_url);
@@ -159,6 +170,8 @@ pwqual_pwncheck_initvt(krb5_context context, int maj_ver, int min_ver,
159170
vt = (struct krb5_pwqual_vtable_st *)vtable;
160171
memset(vt, 0, sizeof *vt);
161172

173+
init_urlencode();
174+
162175
vt->name = "pwncheck";
163176
vt->check = pwqual_pwncheck_check;
164177
syslog(LOG_DEBUG,"pwncheck: initvt: Initiated");

0 commit comments

Comments
 (0)