diff --git a/pam/Makefile.am b/pam/Makefile.am
index ff8f0ba05b20272a64b05817c8e01f4506ce93d6..dcdaa51625e31c123a225fd34e721c1441441dd5 100644
--- a/pam/Makefile.am
+++ b/pam/Makefile.am
@@ -10,7 +10,8 @@ noinst_LIBRARIES = libgtest.a
 
 libauthclient_la_SOURCES = \
 	auth_client.c auth_client.h \
-	cbuf.c cbuf.h
+	cbuf.c cbuf.h \
+	quote.c quote.h
 libauthclient_la_includedir = $(includedir)/authclient
 libauthclient_la_include_HEADERS =  auth_client.h
 
diff --git a/pam/auth_client.c b/pam/auth_client.c
index 98789be6782576b9a68563b57f9f0560d8c82dcd..ae538d2e29705f53b5bea129618bbdd3786e550c 100644
--- a/pam/auth_client.c
+++ b/pam/auth_client.c
@@ -10,6 +10,7 @@
 #include <curl/curl.h>
 #include "auth_client.h"
 #include "cbuf.h"
+#include "quote.h"
 
 #define CURL_CHECK(x) { \
   int _err = (x); if (_err != CURLE_OK) { return auth_client_err_from_curl(_err); } \
@@ -147,6 +148,7 @@ static char *quote(const char *s) {
     case '+':
     case '$':
     case ',':
+    case '%':
       sprintf(optr, "%%%02X", (int)(*s));
       optr += 3;
       break;
@@ -167,7 +169,7 @@ 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_value = quote(value);
+  char *quoted_value = auth_client_quote(value);
   if (form_data->size != 0) {
     cbuf_append(form_data, "&", 1);
   }
diff --git a/pam/quote.c b/pam/quote.c
new file mode 100644
index 0000000000000000000000000000000000000000..da14be4f54aaccea7cb4773ee133ec2f8c1abe39
--- /dev/null
+++ b/pam/quote.c
@@ -0,0 +1,30 @@
+#include <stdlib.h>
+#include "quote.h"
+
+/* Converts a hex character to its integer value */
+static char from_hex(char ch) {
+  return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
+}
+
+/* Converts an integer value to its hex character*/
+static char to_hex(char code) {
+  static const char hex[] = "0123456789abcdef";
+  return hex[code & 15];
+}
+
+/* Returns a url-encoded version of str */
+/* IMPORTANT: be sure to free() the returned string after use */
+char *auth_client_quote(const char *str) {
+  char *pstr = str, *buf = malloc(strlen(str) * 3 + 1), *pbuf = buf;
+  while (*pstr) {
+    if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') 
+      *pbuf++ = *pstr;
+    else if (*pstr == ' ') 
+      *pbuf++ = '+';
+    else 
+      *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
+    pstr++;
+  }
+  *pbuf = '\0';
+  return buf;
+}
diff --git a/pam/quote.h b/pam/quote.h
new file mode 100644
index 0000000000000000000000000000000000000000..55923125dbfc0bd426609db9fa04f18bb839d514
--- /dev/null
+++ b/pam/quote.h
@@ -0,0 +1,6 @@
+#ifndef __libauthclient_quote_h
+#define __libauthclient_quote_h 1
+
+char *auth_client_quote(const char *);
+
+#endif