UTF-8 and LDAP

Juergen Hasch Hasch at t-online.de
Sat Feb 23 11:11:05 GMT 2002


Hi Andrew,

here is the patch for UTF-8 support with LDAP.
Actually these are three patches:
1. Add push_utf8_pstring and push_utf8_fstring I forgot last time.
   Remove unused base_ptr in function call.

2. Convert some strings to/from UTF-8 when calling LDAP functions.
   I assume here that not all parameters need to be in UTF-8.
   Namely in ldap_search only the filter expression needs to be UTF-8,
   base and attributes should not contain non-ascii chars. 
   Received strings from LDAP get UTF-8 converted in ads_pull_string
   and ads_dump_string.
   For ldap_modify_ext_s I needed to allocate space for the strings after
   UTF-8 conversion using talloc_strdup in ads_mod_ber / ads_mod_var.

3. Replace all printf/fprintf function calls in wbinfo.c with
   d_printf/d_fprintf. This way CH_DISPLAY will be used for
   user output. No really critical fix :-)

These patches work for me, I get german characters with 
"net ads", "wbinfo" and "getent". 
...Juergen

--- lib/charcnv.orig	Sat Feb 23 19:16:47 2002
+++ lib/charcnv.c	Sat Feb 23 13:20:32 2002
@@ -400,7 +400,7 @@
 dest_len is the maximum length allowed in the destination. If dest_len
 is -1 then no maxiumum is used
 ****************************************************************************/
-int push_utf8(const void *base_ptr, void *dest, const char *src, int dest_len, int flags)
+int push_utf8(void *dest, const char *src, int dest_len, int flags)
 {
 	int src_len = strlen(src);
 	pstring tmpbuf;
@@ -423,6 +423,16 @@
 	return convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len);
 }
 
+int push_utf8_fstring(void *dest, const char *src)
+{
+	return push_utf8(dest, src, sizeof(fstring), STR_TERMINATE);
+}
+
+int push_utf8_pstring(void *dest, const char *src)
+{
+	return push_utf8(dest, src, sizeof(pstring), STR_TERMINATE);
+}
+
 /****************************************************************************
 copy a string from a ucs2 source to a unix char* destination
 flags can have:
@@ -476,7 +486,7 @@
 return the number of bytes occupied by the string in src
 the resulting string in "dest" is always null terminated
 ****************************************************************************/
-int pull_utf8(const void *base_ptr, char *dest, const void *src, int dest_len, int src_len, int flags)
+int pull_utf8(char *dest, const void *src, int dest_len, int src_len, int flags)
 {
 	int ret;
 
@@ -494,12 +504,12 @@

 int pull_utf8_pstring(char *dest, const void *src)
 {
-	return pull_utf8(NULL, dest, src, sizeof(pstring), -1, STR_TERMINATE);
+	return pull_utf8(dest, src, sizeof(pstring), -1, STR_TERMINATE);
 }

 int pull_utf8_fstring(char *dest, const void *src)
 {
-	return pull_utf8(NULL, dest, src, sizeof(fstring), -1, STR_TERMINATE);
+	return pull_utf8(dest, src, sizeof(fstring), -1, STR_TERMINATE);
 }

 /****************************************************************************

--- libads/ldap.orig	Sun Feb 17 16:17:44 2002
+++ libads/ldap.c	Sat Feb 23 19:01:10 2002
@@ -63,15 +63,17 @@
 			 const char **attrs, void **res)
 {
 	struct timeval timeout;
+	fstring utf8_exp;
 	int rc;

 	timeout.tv_sec = ADS_SEARCH_TIMEOUT;
 	timeout.tv_usec = 0;
 	*res = NULL;
+	pull_utf8_fstring(utf8_exp, exp);
 	rc = ldap_search_ext_s(ads->ld,
 			       bind_path, scope,
-			       exp, (char **) attrs, 0, NULL, NULL,
+			       utf8_exp, (char **) attrs, 0, NULL, NULL,
 			       &timeout, LDAP_NO_LIMIT, (LDAPMessage **)res);
 	return ADS_ERROR(rc);
 }
@@ -237,12 +242,13 @@
 /*
   add an attribute to the list, with values list to be built from args
 */
ADS_STATUS ads_mod_add_var(TALLOC_CTX *ctx, ADS_MODLIST *mods,
 			   int mod_op, char *name, ...)
 {
 	va_list ap;
 	int num_vals, i, do_op;
 	char *value, **values;
+	fstring utf8_value;

 	/* count the number of values */
 	va_start(ap, name);
@@ -254,8 +260,12 @@
 			return ADS_ERROR(LDAP_NO_MEMORY);
 		va_start(ap, name);
 		for (i=0; (value = (char *) va_arg(ap, char *)) &&
-			     i < num_vals; i++)
-			values[i] = value;
+			     i < num_vals; i++) {
+			push_utf8_fstring(utf8_value,value);
+			values[i] = talloc_strdup(ctx,utf8_value);
+			}
 		va_end(ap);
 		values[i] = NULL;
 		do_op = mod_op;
@@ -266,12 +276,13 @@
 	return ads_modlist_add(ctx, mods, do_op, name, values);
 }

ADS_STATUS ads_mod_add_ber(TALLOC_CTX *ctx, ADS_MODLIST *mods,
 			   int mod_op, char *name, ...)
 {
 	va_list ap;
 	int num_vals, i, do_op;
 	char *value, **values;
+	fstring utf8_value;

 	/* count the number of values */
 	va_start(ap, name);
@@ -284,8 +295,13 @@
 			return ADS_ERROR(LDAP_NO_MEMORY);
 		va_start(ap, name);
 		for (i=0; (value = (char *) va_arg(ap, char *)) &&
-			     i < num_vals; i++)
-			values[i] = value;
+			     i < num_vals; i++) {
+			push_utf8_fstring(utf8_value,value);
+			values[i] = talloc_strdup(ctx,utf8_value);
+			}
 		va_end(ap);
 		values[i] = NULL;
 		do_op = mod_op;
@@ -375,7 +391,6 @@
 ADS_STATUS ads_gen_add(ADS_STRUCT *ads, const char *new_dn, ADS_MODLIST mods)
 {
 	int i;
-
 	/* find the end of the list, marked by NULL or -1 */
 	for(i=0;(mods[i]!=0)&&(mods[i]!=(LDAPMod *) -1);i++);
 	/* make sure the end of the list is NULL */
@@ -436,22 +451,22 @@

 	if (!(samAccountName = talloc_asprintf(ctx, "%s$", hostname)))
 		goto done;
	if (!(controlstr = talloc_asprintf(ctx, "%u",
		   UF_DONT_EXPIRE_PASSWD | UF_WORKSTATION_TRUST_ACCOUNT |
 		   UF_TRUSTED_FOR_DELEGATION | UF_USE_DES_KEY_ONLY)))
 		goto done;

 	if (!(mods = ads_init_mods(ctx)))
 		goto done;
-
-	ads_mod_add(ctx, &mods, "cn", hostname);
+
+	ads_mod_add(ctx, &mods, "cn", (char *)hostname);
 	ads_mod_add(ctx, &mods, "sAMAccountName", samAccountName);
 	ads_mod_add_var(ctx, &mods, LDAP_MOD_ADD, "objectClass",
 			"top", "person", "organizationalPerson",
 			"user", "computer", NULL);
 	ads_mod_add(ctx, &mods, "userPrincipalName", host_upn);
 	ads_mod_add(ctx, &mods, "servicePrincipalName", host_spn);
-	ads_mod_add(ctx, &mods, "dNSHostName", hostname);
+	ads_mod_add(ctx, &mods, "dNSHostName", (char *)hostname);
 	ads_mod_add(ctx, &mods, "userAccountControl", controlstr);
 	ads_mod_add(ctx, &mods, "operatingSystem", "Samba");
 	ads_mod_add(ctx, &mods, "operatingSystemVersion", VERSION);
@@ -497,8 +512,10 @@
 static void dump_string(const char *field, struct berval **values)
 {
 	int i;
+	fstring utf8_val;
 	for (i=0; values[i]; i++) {
-		printf("%s: %s\n", field, values[i]->bv_val);
+		pull_utf8_fstring(utf8_val,values[i]->bv_val);
+		d_printf("%s: %s\n", field, utf8_val);
 	}
 }

@@ -681,12 +698,16 @@
 {
 	char **values;
 	char *ret = NULL;
+	fstring utf8_field;

-	values = ldap_get_values(ads->ld, msg, field);
+	push_utf8_fstring(utf8_field,field);
+	values = ldap_get_values(ads->ld, msg, utf8_field);
 	if (!values) return NULL;
 	
 	if (values[0]) {
-		ret = talloc_strdup(mem_ctx, values[0]);
+		fstring utf8_string;
+		pull_utf8_fstring(utf8_string,values[0]);
+		ret = talloc_strdup(mem_ctx, utf8_string);
 	}
 	ldap_value_free(values);
 	return ret;
@@ -699,7 +720,9 @@
 		     void *msg, const char *field, uint32 *v)
 {
 	char **values;
+	fstring utf8_field;
 
+	push_utf8_fstring(utf8_field,field);
 	values = ldap_get_values(ads->ld, msg, field);
 	if (!values) return False;
 	if (!values[0]) {
@@ -715,13 +738,15 @@
 /*
   pull a single DOM_SID from a ADS result
 */
BOOL ads_pull_sid(ADS_STRUCT *ads,
 		  void *msg, const char *field, DOM_SID *sid)
 {
 	struct berval **values;
 	BOOL ret = False;
+	fstring utf8_field;

-	values = ldap_get_values_len(ads->ld, msg, field);
+	push_utf8_fstring(utf8_field,field);
+	values = ldap_get_values_len(ads->ld, msg, utf8_field);

 	if (!values) return False;

@@ -743,8 +768,10 @@
 	struct berval **values;
 	BOOL ret;
 	int count, i;
-
-	values = ldap_get_values_len(ads->ld, msg, field);
+	fstring utf8_field;
+
+	push_utf8_fstring(utf8_field,field);
+	values = ldap_get_values_len(ads->ld, msg, utf8_field);
 
 	if (!values) return 0;
 
--- nsswitch/wbinfo.orig	Tue Feb 19 21:01:05 2002
+++ nsswitch/wbinfo.c	Thu Feb 21 23:18:48 2002
@@ -42,7 +42,7 @@
 
 	if (winbindd_request(WINBINDD_INFO, NULL, &response) !=
 	    NSS_STATUS_SUCCESS) {
-		printf("could not obtain winbind seperator!\n");
+		d_printf("could not obtain winbind seperator!\n");
 		/* HACK: (this module should not call lp_ funtions) */
 		return *lp_winbind_separator();
 	}
@@ -50,7 +50,7 @@
 	winbind_separator = response.data.info.winbind_separator;
 
 	if (!winbind_separator) {
-		printf("winbind separator was NULL!\n");
+		d_printf("winbind separator was NULL!\n");
 		/* HACK: (this module should not call lp_ funtions) */
 		return *lp_winbind_separator();
 	}
@@ -70,7 +70,7 @@
 
 	if (winbindd_request(WINBINDD_DOMAIN_NAME, NULL, &response) !=
 	    NSS_STATUS_SUCCESS) {
-		printf("could not obtain winbind domain name!\n");
+		d_printf("could not obtain winbind domain name!\n");
 		
 		/* HACK: (this module should not call lp_ funtions) */
 		return lp_workgroup();
@@ -124,7 +124,7 @@
 		return False;
 
 	for (i = 0; i < response.data.num_entries; i++)
-		printf("%d\n", (int)((gid_t *)response.extra_data)[i]);
+		d_printf("%d\n", (int)((gid_t *)response.extra_data)[i]);
 
 	SAFE_FREE(response.extra_data);
 
@@ -153,7 +153,7 @@
 		char *extra_data = (char *)response.extra_data;
 
 		while(next_token(&extra_data, name, ",", sizeof(fstring)))
-			printf("%s\n", name);
+			d_printf("%s\n", name);
 
 		SAFE_FREE(response.extra_data);
 	}
@@ -178,7 +178,7 @@
 	/* Display response */
 	if (response.extra_data) {
 		char *extra_data = (char *)response.extra_data;
-		printf("%s", extra_data);
+		d_printf("%s", extra_data);
 		SAFE_FREE(response.extra_data);
 	}
 
@@ -200,9 +200,9 @@
         if (result) {
 
                 if (response.data.num_entries == 0) {
-                        printf("Secret is good\n");
+                        d_printf("Secret is good\n");
                 } else {
-                        printf("Secret is bad\n0x%08x\n", 
+                        d_printf("Secret is bad\n0x%08x\n", 
 			       response.data.num_entries);
                 }
 
@@ -232,7 +232,7 @@
 
 	/* Display response */
 
-	printf("%s\n", response.data.sid.sid);
+	d_printf("%s\n", response.data.sid.sid);
 
 	return True;
 }
@@ -257,7 +257,7 @@
 
 	/* Display response */
 
-	printf("%s\n", response.data.sid.sid);
+	d_printf("%s\n", response.data.sid.sid);
 
 	return True;
 }
@@ -282,7 +282,7 @@
 
 	/* Display response */
 
-	printf("%d\n", (int)response.data.uid);
+	d_printf("%d\n", (int)response.data.uid);
 
 	return True;
 }
@@ -305,7 +305,7 @@
 
 	/* Display response */
 
-	printf("%d\n", (int)response.data.gid);
+	d_printf("%d\n", (int)response.data.gid);
 
 	return True;
 }
@@ -330,7 +330,7 @@
 
 	/* Display response */
 
-	printf("[%s]\\[%s] %d\n", response.data.name.dom_name, response.data.name.name, response.data.name.type);
+	d_printf("[%s]\\[%s] %d\n", response.data.name.dom_name, response.data.name.name, response.data.name.type);
 
 	return True;
 }
@@ -356,7 +356,7 @@
 
 	/* Display response */
 
-	printf("%s %d\n", response.data.sid.sid, response.data.sid.type);
+	d_printf("%s %d\n", response.data.sid.sid, response.data.sid.type);
 
 	return True;
 }
@@ -389,10 +389,10 @@
 
 	/* Display response */
 
-        printf("plaintext password authentication %s\n", 
+        d_printf("plaintext password authentication %s\n", 
                (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
 
-	printf("error code was %s (0x%x)\n", response.data.auth.nt_status_string, response.data.auth.nt_status);
+	d_printf("error code was %s (0x%x)\n", response.data.auth.nt_status_string, response.data.auth.nt_status);
 
         return result == NSS_STATUS_SUCCESS;
 }
@@ -441,10 +441,10 @@
 
 	/* Display response */
 
-        printf("challenge/response password authentication %s\n", 
+        d_printf("challenge/response password authentication %s\n", 
                (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
 
-	printf("error code was %s (0x%x)\n", 
+	d_printf("error code was %s (0x%x)\n", 
 	       response.data.auth.nt_status_string, 
 	       response.data.auth.nt_status);
 
@@ -476,7 +476,7 @@
 	extra_data = (char *)response.extra_data;
 
 	while(next_token(&extra_data, name, ",", sizeof(fstring)))
-		printf("%s\n", name);
+		d_printf("%s\n", name);
 	
 	SAFE_FREE(response.extra_data);
 
@@ -506,7 +506,7 @@
 	extra_data = (char *)response.extra_data;
 
 	while(next_token(&extra_data, name, ",", sizeof(fstring)))
-		printf("%s\n", name);
+		d_printf("%s\n", name);
 
 	SAFE_FREE(response.extra_data);
 	
@@ -537,7 +537,7 @@
 	if (!secrets_store(SECRETS_AUTH_USER, username, strlen(username) + 1) ||
 	    !secrets_store(SECRETS_AUTH_DOMAIN, domain, strlen(domain) + 1) ||
 		!secrets_store(SECRETS_AUTH_PASSWORD, password, strlen(password) + 1)) {
-		fprintf(stderr, "error storing authenticated user info\n");
+		d_fprintf(stderr, "error storing authenticated user info\n");
 		return False;
 	}
 
@@ -552,7 +552,7 @@
 
 	/* Display response */
 
-        printf("'ping' to winbindd %s\n", 
+        d_printf("'ping' to winbindd %s\n", 
                (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
 
         return result == NSS_STATUS_SUCCESS;
@@ -562,22 +562,22 @@
 
 static void usage(void)
 {
-	printf("Usage: wbinfo -ug | -n name | -sSY sid | -UG uid/gid | -tm "
+	d_printf("Usage: wbinfo -ug | -n name | -sSY sid | -UG uid/gid | -tm "
                "| -a user%%password\n");
-	printf("\t-u\t\t\tlists all domain users\n");
-	printf("\t-g\t\t\tlists all domain groups\n");
-	printf("\t-n name\t\t\tconverts name to sid\n");
-	printf("\t-s sid\t\t\tconverts sid to name\n");
-	printf("\t-U uid\t\t\tconverts uid to sid\n");
-	printf("\t-G gid\t\t\tconverts gid to sid\n");
-	printf("\t-S sid\t\t\tconverts sid to uid\n");
-	printf("\t-Y sid\t\t\tconverts sid to gid\n");
-	printf("\t-t\t\t\tcheck shared secret\n");
-	printf("\t-m\t\t\tlist trusted domains\n");
-	printf("\t-r user\t\t\tget user groups\n");
-	printf("\t-a user%%password\tauthenticate user\n");
-	printf("\t-p 'ping' winbindd to see if it is alive\n");
-	printf("\t--sequence\t\tshow sequence numbers of all domains\n");
+	d_printf("\t-u\t\t\tlists all domain users\n");
+	d_printf("\t-g\t\t\tlists all domain groups\n");
+	d_printf("\t-n name\t\t\tconverts name to sid\n");
+	d_printf("\t-s sid\t\t\tconverts sid to name\n");
+	d_printf("\t-U uid\t\t\tconverts uid to sid\n");
+	d_printf("\t-G gid\t\t\tconverts gid to sid\n");
+	d_printf("\t-S sid\t\t\tconverts sid to uid\n");
+	d_printf("\t-Y sid\t\t\tconverts sid to gid\n");
+	d_printf("\t-t\t\t\tcheck shared secret\n");
+	d_printf("\t-m\t\t\tlist trusted domains\n");
+	d_printf("\t-r user\t\t\tget user groups\n");
+	d_printf("\t-a user%%password\tauthenticate user\n");
+	d_printf("\t-p 'ping' winbindd to see if it is alive\n");
+	d_printf("\t--sequence\t\tshow sequence numbers of all domains\n");
 }
 
 /* Main program */
@@ -632,7 +632,7 @@
 	}
 
 	if (!lp_load(dyn_CONFIGFILE, True, False, False)) {
-		fprintf(stderr, "wbinfo: error opening config file %s. Error was %s\n",
+		d_fprintf(stderr, "wbinfo: error opening config file %s. Error was %s\n",
 			dyn_CONFIGFILE, strerror(errno));
 		exit(1);
 	}
@@ -652,7 +652,7 @@
 
 	while((opt = poptGetNextOpt(pc)) != -1) {
 		if (got_command) {
-			fprintf(stderr, "No more than one command may be specified "
+			d_fprintf(stderr, "No more than one command may be specified "
 				"at once.\n");
 			exit(1);
 		}
@@ -669,76 +669,76 @@
 			exit(0);
 		case 'u':
 			if (!print_domain_users()) {
-				printf("Error looking up domain users\n");
+				d_printf("Error looking up domain users\n");
 				return 1;
 			}
 			break;
 		case 'g':
 			if (!print_domain_groups()) {
-				printf("Error looking up domain groups\n");
+				d_printf("Error looking up domain groups\n");
 				return 1;
 			}
 			break;
 		case 's':
 			if (!wbinfo_lookupsid(string_arg)) {
-				printf("Could not lookup sid %s\n", string_arg);
+				d_printf("Could not lookup sid %s\n", string_arg);
 				return 1;
 			}
 			break;
 		case 'n':
 			if (!wbinfo_lookupname(string_arg)) {
-				printf("Could not lookup name %s\n", string_arg);
+				d_printf("Could not lookup name %s\n", string_arg);
 				return 1;
 			}
 			break;
 		case 'U':
 			if (!wbinfo_uid_to_sid(int_arg)) {
-				printf("Could not convert uid %d to sid\n", int_arg);
+				d_printf("Could not convert uid %d to sid\n", int_arg);
 				return 1;
 			}
 			break;
 		case 'G':
 			if (!wbinfo_gid_to_sid(int_arg)) {
-				printf("Could not convert gid %d to sid\n",
+				d_printf("Could not convert gid %d to sid\n",
 				       int_arg);
 				return 1;
 			}
 			break;
 		case 'S':
 			if (!wbinfo_sid_to_uid(string_arg)) {
-				printf("Could not convert sid %s to uid\n",
+				d_printf("Could not convert sid %s to uid\n",
 				       string_arg);
 				return 1;
 			}
 			break;
 		case 'Y':
 			if (!wbinfo_sid_to_gid(string_arg)) {
-				printf("Could not convert sid %s to gid\n",
+				d_printf("Could not convert sid %s to gid\n",
 				       string_arg);
 				return 1;
 			}
 			break;
 		case 't':
 			if (!wbinfo_check_secret()) {
-				printf("Could not check secret\n");
+				d_printf("Could not check secret\n");
 				return 1;
 			}
 			break;
 		case 'm':
 			if (!wbinfo_list_domains()) {
-				printf("Could not list trusted domains\n");
+				d_printf("Could not list trusted domains\n");
 				return 1;
 			}
 			break;
 		case OPT_SEQUENCE:
 			if (!wbinfo_show_sequence()) {
-				printf("Could not show sequence numbers\n");
+				d_printf("Could not show sequence numbers\n");
 				return 1;
 			}
 			break;
 		case 'r':
 			if (!wbinfo_get_usergroups(string_arg)) {
-				printf("Could not get groups for user %s\n", 
+				d_printf("Could not get groups for user %s\n", 
 				       string_arg);
 				return 1;
 			}
@@ -747,13 +747,13 @@
                         BOOL got_error = False;
 
                         if (!wbinfo_auth(string_arg)) {
-                                printf("Could not authenticate user %s with "
+                                d_printf("Could not authenticate user %s with "
                                        "plaintext password\n", string_arg);
                                 got_error = True;
                         }
 
                         if (!wbinfo_auth_crap(string_arg)) {
-                                printf("Could not authenticate user %s with "
+                                d_printf("Could not authenticate user %s with "
                                        "challenge/response\n", string_arg);
                                 got_error = True;
                         }
@@ -765,7 +765,7 @@
                 case 'p': {
 
                         if (!wbinfo_ping()) {
-                                printf("could not ping winbindd!\n");
+                                d_printf("could not ping winbindd!\n");
                                 return 1;
 			}
                         break;
@@ -776,7 +776,7 @@
 			}
 			break;
 		default:
-			fprintf(stderr, "Invalid option\n");
+			d_fprintf(stderr, "Invalid option\n");
 			usage();
 			return 1;
 		}






More information about the samba-technical mailing list