autofs-5.0.1 - add base64 password encode From: Ian Kent <raven@themaw.net> Add a trivial base64 password endoder to obscure password entries in autofs_ldap_auth.conf. Note that there is no way to encrypt the passwords without storing a password somewhere because there is no interactive input to allow a pass phrase or password to be input. The base64 encoded string can be generated using the coreutils base64 utility with: echo -n "<your text string>" | base64 autofs will use the encoded string if it finds a valid entry "encoded_secret=<encoded string>" in autofs_ldap_auth.conf. If this cvalue is present it will override a "secret=<string>" entry. --- include/base64.h | 11 ++ modules/Makefile | 4 modules/base64.c | 225 ++++++++++++++++++++++++++++++++++++++++++ modules/lookup_ldap.c | 29 ++++- samples/autofs_ldap_auth.conf | 5 5 files changed, 268 insertions(+), 6 deletions(-) create mode 100644 include/base64.h create mode 100644 modules/base64.c --- /dev/null +++ autofs-5.0.1/include/base64.h @@ -0,0 +1,11 @@ + +#ifndef BASE64_H +#define BASE64_H + +#include <stdlib.h> +#include <string.h> + +int base64_encode(char *, size_t, char *, size_t); +size_t base64_decode(char *, char *, size_t); + +#endif --- autofs-5.0.1.orig/modules/Makefile +++ autofs-5.0.1/modules/Makefile @@ -90,9 +90,9 @@ cyrus-sasl.o: cyrus-sasl.c cyrus-sasl-extern.o: cyrus-sasl-extern.c $(CC) $(CFLAGS) $(LDAP_FLAGS) -c $< -lookup_ldap.so: lookup_ldap.c dclist.o $(SASL_OBJ) +lookup_ldap.so: lookup_ldap.c dclist.o base64.o $(SASL_OBJ) $(CC) $(SOLDFLAGS) $(CFLAGS) $(LDAP_FLAGS) -o lookup_ldap.so \ - lookup_ldap.c dclist.o $(SASL_OBJ) \ + lookup_ldap.c dclist.o base64.o $(SASL_OBJ) \ $(AUTOFS_LIB) $(LIBLDAP) $(LIBRESOLV) $(STRIP) lookup_ldap.so --- /dev/null +++ autofs-5.0.1/modules/base64.c @@ -0,0 +1,225 @@ +#include <base64.h> + +/* + * characters used for Base64 encoding + */ +static const char *BASE64_CHARS = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/* + * encode three bytes using base64 (RFC 3548) + * + * @param triple three bytes that should be encoded + * @param result buffer of four characters where the result is stored + */ +static void _base64_encode_triple(char triple[3], char result[4]) +{ + int tripleValue, i; + + tripleValue = triple[0]; + tripleValue *= 256; + tripleValue += triple[1]; + tripleValue *= 256; + tripleValue += triple[2]; + + for (i=0; i<4; i++) { + result[3 - i] = BASE64_CHARS[tripleValue % 64]; + tripleValue /= 64; + } +} + +/* + * encode an array of bytes using Base64 (RFC 3548) + * + * @param source the source buffer + * @param sourcelen the length of the source buffer + * @param target the target buffer + * @param targetlen the length of the target buffer + * @return 1 on success, 0 otherwise + */ +int base64_encode(char *source, size_t sourcelen, char *target, size_t targetlen) +{ + /* check if the result will fit in the target buffer */ + if ((sourcelen + 2)/ 3*4 > targetlen - 1) + return 0; + + /* encode all full triples */ + while (sourcelen >= 3) { + _base64_encode_triple(source, target); + sourcelen -= 3; + source += 3; + target += 4; + } + + /* encode the last one or two characters */ + if (sourcelen > 0) { + unsigned char temp[3]; + memset(temp, 0, sizeof(temp)); + memcpy(temp, source, sourcelen); + _base64_encode_triple(temp, target); + target[3] = '='; + if (sourcelen == 1) + target[2] = '='; + target += 4; + } + + /* terminate the string */ + target[0] = 0; + + return 1; +} + +/* + * determine the value of a base64 encoding character + * + * @param base64char the character of which the value is searched + * @return the value in case of success (0-63), -1 on failure + */ +static int _base64_char_value(char base64char) +{ + if (base64char >= 'A' && base64char <= 'Z') + return base64char-'A'; + if (base64char >= 'a' && base64char <= 'z') + return base64char-'a'+26; + if (base64char >= '0' && base64char <= '9') + return base64char-'0'+2*26; + if (base64char == '+') + return 2*26+10; + if (base64char == '/') + return 2*26+11; + return -1; +} + +/* + * decode a 4 char base64 encoded byte triple + * + * @param quadruple the 4 characters that should be decoded + * @param result the decoded data + * @return lenth of the result (1, 2 or 3), 0 on failure + */ +static int _base64_decode_triple(char quadruple[4], char *result) +{ + int i, triple_value, bytes_to_decode = 3, only_equals_yet = 1; + int char_value[4]; + + for (i=0; i<4; i++) + char_value[i] = _base64_char_value(quadruple[i]); + + /* check if the characters are valid */ + for (i=3; i>=0; i--) { + if (char_value[i]<0) { + if (only_equals_yet && quadruple[i]=='=') { + /* we will ignore this character anyway, make it + * something that does not break our calculations */ + char_value[i]=0; + bytes_to_decode--; + continue; + } + return 0; + } + /* after we got a real character, no other '=' are allowed anymore */ + only_equals_yet = 0; + } + + /* if we got "====" as input, bytes_to_decode is -1 */ + if (bytes_to_decode < 0) + bytes_to_decode = 0; + + /* make one big value out of the partial values */ + triple_value = char_value[0]; + triple_value *= 64; + triple_value += char_value[1]; + triple_value *= 64; + triple_value += char_value[2]; + triple_value *= 64; + triple_value += char_value[3]; + + /* break the big value into bytes */ + for (i=bytes_to_decode; i<3; i++) + triple_value /= 256; + for (i=bytes_to_decode-1; i>=0; i--) { + result[i] = triple_value%256; + triple_value /= 256; + } + + return bytes_to_decode; +} + +/* + * decode base64 encoded data + * + * @param source the encoded data (zero terminated) + * @param target pointer to the target buffer + * @param targetlen length of the target buffer + * @return length of converted data on success, -1 otherwise + */ +size_t base64_decode(char *source, char *target, size_t targetlen) +{ + char *src, *tmpptr; + char quadruple[4], tmpresult[3]; + int i, tmplen = 3; + size_t converted = 0; + + /* concatinate '===' to the source to handle unpadded base64 data */ + src = malloc(strlen(source)+5); + if (src == NULL) + return -1; + strcpy(src, source); + strcat(src, "===="); + tmpptr = src; + + memset(target, 0, targetlen); + + /* convert as long as we get a full result */ + while (tmplen == 3) { + /* get 4 characters to convert */ + for (i = 0; i < 4; i++) { + /* skip invalid characters - we won't reach the end */ + while (*tmpptr != '=' && _base64_char_value(*tmpptr) < 0) + tmpptr++; + quadruple[i] = *(tmpptr++); + } + + /* convert the characters */ + tmplen = _base64_decode_triple(quadruple, tmpresult); + + /* check if the fit in the result buffer */ + if (targetlen < tmplen) { + free(src); + return -1; + } + + /* put the partial result in the result buffer */ + memcpy(target, tmpresult, tmplen); + target += tmplen; + targetlen -= tmplen; + converted += tmplen; + } + + free(src); + return converted; +} + +#if 0 +#include <stdio.h> + +int main(int argc, char **argv) +{ + char *source = "testt(estt#wot%est'ing"; + int source_len = strlen(source); + char dest[80]; + int dest_len = 79; + char decoded[80]; + int decode_len = 79; + int len; + + printf("string %s\n", source); + + if (base64_encode(source, source_len, dest, dest_len)) + printf("encoded %s len %d\n", dest, strlen(dest)); + + len = base64_decode(dest, decoded, decode_len); + if (len != -1) + printf("decoded %s len %d\n", decoded, len); +} +#endif --- autofs-5.0.1.orig/modules/lookup_ldap.c +++ autofs-5.0.1/modules/lookup_ldap.c @@ -35,6 +35,7 @@ #include "automount.h" #include "nsswitch.h" #include "lookup_ldap.h" +#include "base64.h" #define MAPFMT_DEFAULT "sun" @@ -1044,9 +1045,12 @@ int parse_ldap_config(unsigned logopt, s if (auth_required == LDAP_AUTH_USESIMPLE || (authtype && authtype_requires_creds(authtype))) { + char *s1 = NULL, *s2 = NULL; ret = get_property(logopt, root, "user", &user); - ret |= get_property(logopt, root, "secret", &secret); - if (ret != 0 || (!user || !secret)) { + ret |= get_property(logopt, root, "secret", &s1); + ret |= get_property(logopt, root, "encoded_secret", &s2); + if (ret != 0 || (!user || (!s1 && !s2))) { +auth_fail: error(logopt, MODPREFIX "%s authentication type requires a username " @@ -1055,12 +1059,29 @@ int parse_ldap_config(unsigned logopt, s free(authtype); if (user) free(user); - if (secret) - free(secret); + if (s1) + free(s1); + if (s2) + free(s2); ret = -1; goto out; } + if (!s2) + secret = s1; + else { + char dec_buf[120]; + int dec_len = base64_decode(s2, dec_buf, 119); + if (dec_len <= 0) + goto auth_fail; + secret = strdup(dec_buf); + if (!secret) + goto auth_fail; + if (s1) + free(s1); + if (s2) + free(s2); + } } else if (auth_required == LDAP_AUTH_REQUIRED && (authtype && !strncmp(authtype, "EXTERNAL", 8))) { ret = get_property(logopt, root, "external_cert", &extern_cert); --- autofs-5.0.1.orig/samples/autofs_ldap_auth.conf +++ autofs-5.0.1/samples/autofs_ldap_auth.conf @@ -79,6 +79,11 @@ secret - This attribute holds the secr include any printable characters that can be used by the selected authentication mechanism. +encoded_secret - This attribute holds the base64 encoded secret used + by authentication mechanisms that require it. If this entry + is present as well as the secret entry this value will take + precedence. + clientprinc - When using GSSAPI authentication, this attribute is consulted to determine the principal name to use when authenticating to the directory server. By default, this will