]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
ITS#9446 - Correctly parse gecos field
authorKonstantin Andreev <grapvar@gmail.com>
Wed, 3 Mar 2021 10:37:19 +0000 (10:37 +0000)
committerQuanah Gibson-Mount <quanah@openldap.org>
Thu, 4 Mar 2021 19:05:23 +0000 (19:05 +0000)
servers/slapd/back-passwd/search.c

index 98d90504263cede193260c81c41ad69af729f131..dd6c5a8d1c03c9f72cb49065e055d0b13f958463 100644 (file)
@@ -321,7 +321,7 @@ pw2entry( Backend *be, struct passwd *pw, Entry *e )
 
 #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.
         */
@@ -332,22 +332,39 @@ pw2entry( Backend *be, struct passwd *pw, Entry *e )
                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 );