diff --git a/lib/heimdal/NTMakefile b/lib/heimdal/NTMakefile index 5cced1a24..833f4ebe2 100644 --- a/lib/heimdal/NTMakefile +++ b/lib/heimdal/NTMakefile @@ -51,7 +51,8 @@ DLLSDKDEPS= \ $(PTHREAD_LIB) \ secur32.lib \ shell32.lib \ - dnsapi.lib + dnsapi.lib \ + shlwapi.lib DEF=$(OBJ)\heimdal.def diff --git a/lib/krb5/config_reg.c b/lib/krb5/config_reg.c index 32240bb3f..2611f9f48 100644 --- a/lib/krb5/config_reg.c +++ b/lib/krb5/config_reg.c @@ -35,9 +35,179 @@ #error config_reg.c is only for Windows #endif +#include + +#ifndef MAX_DWORD +#define MAX_DWORD 0xFFFFFFFF +#endif + #define REGPATH_KERBEROS "SOFTWARE\\Kerberos" #define REGPATH_HEIMDAL "SOFTWARE\\Heimdal" +/** + * Store a string as a registry value of the specified type + * + * The following registry types are handled: + * + * - REG_DWORD: The string is converted to a number. + * + * - REG_SZ: The string is stored as is. + * + * - REG_EXPAND_SZ: The string is stored as is. + * + * - REG_MULTI_SZ: + * + * . If a separator is specified, the input string is broken + * up into multiple strings and stored as a multi-sz. + * + * . If no separator is provided, the input string is stored + * as a multi-sz. + * + * - REG_NONE: + * + * . If the string is all numeric, it will be stored as a + * REG_DWORD. + * + * . Otherwise, the string is stored as a REG_SZ. + * + * Other types are rejected. + * + * If cb_data is MAX_DWORD, the string pointed to by data must be nul-terminated + * otherwise a buffer overrun will occur. + * + * @param [in]valuename Name of the registry value to be modified or created + * @param [in]type Type of the value. REG_NONE if unknown + * @param [in]data The input string to be stored in the registry. + * @param [in]cb_data Size of the input string in bytes. MAX_DWORD if unknown. + * @param [in]separator Separator character for parsing strings. + * + * @retval 0 if success or non-zero on error. + * If non-zero is returned, an error message has been set using + * krb5_set_error_message(). + * + */ +int +_krb5_store_string_to_reg_value(krb5_context context, + HKEY key, const char * valuename, + DWORD type, const char *data, DWORD cb_data, + const char * separator) +{ + LONG rcode; + DWORD dwData; + BYTE static_buffer[16384]; + BYTE *pbuffer = &static_buffer[0]; + + if (data == NULL) + { + if (context) + krb5_set_error_message(context, 0, + "'data' must not be NULL"); + return -1; + } + + if (cb_data == MAX_DWORD) + { + cb_data = (DWORD)strlen(data) + 1; + } + else if ((type == REG_MULTI_SZ && cb_data >= sizeof(static_buffer) - 1) || + cb_data >= sizeof(static_buffer)) + { + if (context) + krb5_set_error_message(context, 0, "cb_data too big"); + return -1; + } + else if (data[cb_data-1] != '\0') + { + memcpy(static_buffer, data, cb_data); + static_buffer[cb_data++] = '\0'; + if (type == REG_MULTI_SZ) + static_buffer[cb_data++] = '\0'; + data = static_buffer; + } + + if (type == REG_NONE) + { + /* + * If input is all numeric, convert to DWORD and save as REG_DWORD. + * Otherwise, store as REG_SZ. + */ + if ( StrToIntExA( data, STIF_SUPPORT_HEX, &dwData) ) + { + type = REG_DWORD; + } else { + type = REG_SZ; + } + } + + switch (type) { + case REG_SZ: + case REG_EXPAND_SZ: + rcode = RegSetValueEx(key, valuename, 0, type, data, cb_data); + if (rcode) + { + if (context) + krb5_set_error_message(context, 0, + "Unexpected error when setting registry value %s gle 0x%x", + valuename, + GetLastError()); + return -1; + } + break; + case REG_MULTI_SZ: + if (separator && *separator) + { + int i; + char *cp; + + if (data != static_buffer) + static_buffer[cb_data++] = '\0'; + + for ( cp = static_buffer; cp < static_buffer+cb_data; cp++) + { + if (*cp == *separator) + *cp = '\0'; + } + + rcode = RegSetValueEx(key, valuename, 0, type, data, cb_data); + if (rcode) + { + if (context) + krb5_set_error_message(context, 0, + "Unexpected error when setting registry value %s gle 0x%x", + valuename, + GetLastError()); + return -1; + } + } + break; + case REG_DWORD: + if ( !StrToIntExA( data, STIF_SUPPORT_HEX, &dwData) ) + { + if (context) + krb5_set_error_message(context, 0, + "Unexpected error when parsing %s as number gle 0x%x", + data, + GetLastError()); + } + + rcode = RegSetValueEx(key, valuename, 0, type, dwData, sizeof(DWORD)); + if (rcode) + { + if (context) + krb5_set_error_message(context, 0, + "Unexpected error when setting registry value %s gle 0x%x", + valuename, + GetLastError()); + return -1; + } + break; + default: + return -1; + } + + return 0; +} + /** * Parse a registry value as a string *