#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
/*
- * if gecos is present, add it as a cn. first process it
+ * if gecos is present, add user's full name as a cn. first process it
* according to standard BSD usage. If the processed cn has
* a space, use the tail as the surname.
*/
ber_str2bv( pw->pw_gecos, 0, 0, &val );
attr_merge_normalize_one( e, ad_desc, &val, NULL );
- s = ber_bvchr( &val, ',' );
- if ( s ) *s = '\0';
+ s = strchr( val.bv_val, (unsigned char)',' );
+ if ( s ) {
+ *s = '\0';
+ val.bv_len = s - val.bv_val;
+ }
- s = ber_bvchr( &val, '&' );
+ s = strchr( val.bv_val, (unsigned char)'&' );
if ( s ) {
- if( val.bv_len + pwlen < sizeof(buf) ) {
- int i = s - val.bv_val;
- strncpy( buf, val.bv_val, i );
- s = buf + i;
- strcpy( s, pw->pw_name );
- *s = TOUPPER((unsigned char)*s);
- strcat( s, val.bv_val + i + 1 );
+ unsigned r = sizeof buf;
+ /* if name with expanded `&` fits in buf */
+ if ( val.bv_len + pwlen <= r ) {
+ char * d = buf;
+
+ for (;;) {
+ size_t const i = s - val.bv_val;
+ memcpy( d, val.bv_val, i );
+ d += i;
+ memcpy( d, pw->pw_name, pwlen );
+ *d = TOUPPER((unsigned char)*pw->pw_name);
+ d += pwlen;
+ r -= pwlen + i;
+ val.bv_len -= i + 1;
+ val.bv_val = s + 1;
+
+ s = strchr( val.bv_val, (unsigned char)'&' );
+ if (!(s && ( val.bv_len + pwlen <= r )))
+ break;
+ }
+ strcpy( d, val.bv_val );
+ val.bv_len = d - buf + val.bv_len;
val.bv_val = buf;
- }
- }
- val.bv_len = strlen( val.bv_val );
+ } // 1st fits
+ } // 1st &
if ( val.bv_len && strcasecmp( val.bv_val, pw->pw_name ) ) {
attr_merge_normalize_one( e, slap_schema.si_ad_cn, &val, NULL );