LCOV - code coverage report
Current view: top level - source4/torture/local - nss_tests.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 395 421 93.8 %
Date: 2024-06-13 04:01:37 Functions: 35 35 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    local testing of the nss wrapper
       5             : 
       6             :    Copyright (C) Guenther Deschner 2009-2010
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : 
      24             : #include "torture/torture.h"
      25             : #include "torture/local/proto.h"
      26             : #include "lib/replace/system/passwd.h"
      27             : 
      28         806 : static bool copy_passwd(struct torture_context *tctx,
      29             :                         const struct passwd *pwd,
      30             :                         struct passwd *p)
      31             : {
      32         806 :         p->pw_name   = talloc_strdup(tctx, pwd->pw_name);
      33         806 :         torture_assert(tctx, (p->pw_name != NULL || pwd->pw_name == NULL), __location__);
      34         806 :         p->pw_passwd = talloc_strdup(tctx, pwd->pw_passwd);
      35         806 :         torture_assert(tctx, (p->pw_passwd != NULL || pwd->pw_passwd == NULL), __location__);
      36         806 :         p->pw_uid    = pwd->pw_uid;
      37         806 :         p->pw_gid    = pwd->pw_gid;
      38         806 :         p->pw_gecos  = talloc_strdup(tctx, pwd->pw_gecos);
      39         806 :         torture_assert(tctx, (p->pw_gecos != NULL || pwd->pw_gecos == NULL), __location__);
      40         806 :         p->pw_dir    = talloc_strdup(tctx, pwd->pw_dir);
      41         806 :         torture_assert(tctx, (p->pw_dir != NULL || pwd->pw_dir == NULL), __location__);
      42         806 :         p->pw_shell  = talloc_strdup(tctx, pwd->pw_shell);
      43         806 :         torture_assert(tctx, (p->pw_shell != NULL || pwd->pw_shell == NULL), __location__);
      44             : 
      45         806 :         return true;
      46             : }
      47             : 
      48         682 : static void print_passwd(struct passwd *pwd)
      49             : {
      50        1364 :         printf("%s:%s:%lu:%lu:%s:%s:%s\n",
      51             :                pwd->pw_name,
      52             :                pwd->pw_passwd,
      53         682 :                (unsigned long)pwd->pw_uid,
      54         682 :                (unsigned long)pwd->pw_gid,
      55             :                pwd->pw_gecos,
      56             :                pwd->pw_dir,
      57             :                pwd->pw_shell);
      58         682 : }
      59             : 
      60             : 
      61         124 : static bool test_getpwnam(struct torture_context *tctx,
      62             :                           const char *name,
      63             :                           struct passwd *pwd_p)
      64             : {
      65             :         struct passwd *pwd;
      66             :         int ret;
      67             : 
      68         124 :         torture_comment(tctx, "Testing getpwnam: %s\n", name);
      69             : 
      70         124 :         errno = 0;
      71         124 :         pwd = getpwnam(name);
      72         124 :         ret = errno;
      73         124 :         torture_assert(tctx, (pwd != NULL), talloc_asprintf(tctx,
      74             :                        "getpwnam(%s) failed - %d - %s",
      75             :                        name, ret, strerror(ret)));
      76             : 
      77         124 :         if (pwd_p != NULL) {
      78         124 :                 torture_assert(tctx, copy_passwd(tctx, pwd, pwd_p), __location__);
      79             :         }
      80             : 
      81         124 :         return true;
      82             : }
      83             : 
      84         124 : static bool test_getpwnam_r(struct torture_context *tctx,
      85             :                             const char *name,
      86             :                             struct passwd *pwd_p)
      87             : {
      88             :         struct passwd pwd, *pwdp;
      89             :         char buffer[4096];
      90             :         int ret;
      91             : 
      92         124 :         torture_comment(tctx, "Testing getpwnam_r: %s\n", name);
      93             : 
      94         124 :         ret = getpwnam_r(name, &pwd, buffer, sizeof(buffer), &pwdp);
      95         124 :         torture_assert(tctx, ret == 0, talloc_asprintf(tctx,
      96             :                        "getpwnam_r(%s) failed - %d - %s",
      97             :                        name, ret, strerror(ret)));
      98             : 
      99         124 :         print_passwd(&pwd);
     100             : 
     101         124 :         if (pwd_p != NULL) {
     102         124 :                 torture_assert(tctx, copy_passwd(tctx, &pwd, pwd_p), __location__);
     103             :         }
     104             : 
     105         124 :         return true;
     106             : }
     107             : 
     108         124 : static bool test_getpwuid(struct torture_context *tctx,
     109             :                           uid_t uid,
     110             :                           struct passwd *pwd_p)
     111             : {
     112             :         struct passwd *pwd;
     113             :         int ret;
     114             : 
     115         124 :         torture_comment(tctx, "Testing getpwuid: %lu\n", (unsigned long)uid);
     116             : 
     117         124 :         errno = 0;
     118         124 :         pwd = getpwuid(uid);
     119         124 :         ret = errno;
     120         124 :         torture_assert(tctx, (pwd != NULL), talloc_asprintf(tctx,
     121             :                        "getpwuid(%lu) failed - %d - %s",
     122             :                        (unsigned long)uid, ret, strerror(ret)));
     123             : 
     124         124 :         print_passwd(pwd);
     125             : 
     126         124 :         if (pwd_p != NULL) {
     127         124 :                 torture_assert(tctx, copy_passwd(tctx, pwd, pwd_p), __location__);
     128             :         }
     129             : 
     130         124 :         return true;
     131             : }
     132             : 
     133         124 : static bool test_getpwuid_r(struct torture_context *tctx,
     134             :                             uid_t uid,
     135             :                             struct passwd *pwd_p)
     136             : {
     137             :         struct passwd pwd, *pwdp;
     138             :         char buffer[4096];
     139             :         int ret;
     140             : 
     141         124 :         torture_comment(tctx, "Testing getpwuid_r: %lu\n", (unsigned long)uid);
     142             : 
     143         124 :         ret = getpwuid_r(uid, &pwd, buffer, sizeof(buffer), &pwdp);
     144         124 :         torture_assert(tctx, ret == 0, talloc_asprintf(tctx,
     145             :                        "getpwuid_r(%lu) failed - %d - %s",
     146             :                        (unsigned long)uid, ret, strerror(ret)));
     147             : 
     148         124 :         print_passwd(&pwd);
     149             : 
     150         124 :         if (pwd_p != NULL) {
     151         124 :                 torture_assert(tctx, copy_passwd(tctx, &pwd, pwd_p), __location__);
     152             :         }
     153             : 
     154         124 :         return true;
     155             : }
     156             : 
     157             : 
     158         762 : static bool copy_group(struct torture_context *tctx,
     159             :                        const struct group *grp,
     160             :                        struct group *g)
     161             : {
     162             :         int i;
     163             : 
     164         762 :         g->gr_name   = talloc_strdup(tctx, grp->gr_name);
     165         762 :         torture_assert(tctx, (g->gr_name != NULL || grp->gr_name == NULL), __location__);
     166         762 :         g->gr_passwd = talloc_strdup(tctx, grp->gr_passwd);
     167         762 :         torture_assert(tctx, (g->gr_passwd != NULL || grp->gr_passwd == NULL), __location__);
     168         762 :         g->gr_gid    = grp->gr_gid;
     169         762 :         g->gr_mem    = NULL;
     170             : 
     171         874 :         for (i=0; grp->gr_mem && grp->gr_mem[i]; i++) {
     172         112 :                 g->gr_mem = talloc_realloc(tctx, g->gr_mem, char *, i + 2);
     173         112 :                 torture_assert(tctx, (g->gr_mem != NULL), __location__);
     174         112 :                 g->gr_mem[i] = talloc_strdup(g->gr_mem, grp->gr_mem[i]);
     175         112 :                 torture_assert(tctx, (g->gr_mem[i] != NULL), __location__);
     176         112 :                 g->gr_mem[i+1] = NULL;
     177             :         }
     178             : 
     179         762 :         return true;
     180             : }
     181             : 
     182         832 : static void print_group(struct group *grp)
     183             : {
     184             :         int i;
     185         832 :         printf("%s:%s:%lu:",
     186             :                grp->gr_name,
     187             :                grp->gr_passwd,
     188         832 :                (unsigned long)grp->gr_gid);
     189             : 
     190         832 :         if ((grp->gr_mem == NULL) || !grp->gr_mem[0]) {
     191         702 :                 printf("\n");
     192         702 :                 return;
     193             :         }
     194             : 
     195         130 :         for (i=0; grp->gr_mem[i+1]; i++) {
     196           0 :                 printf("%s,", grp->gr_mem[i]);
     197             :         }
     198         130 :         printf("%s\n", grp->gr_mem[i]);
     199             : }
     200             : 
     201         124 : static bool test_getgrnam(struct torture_context *tctx,
     202             :                           const char *name,
     203             :                           struct group *grp_p)
     204             : {
     205             :         struct group *grp;
     206             :         int ret;
     207             : 
     208         124 :         torture_comment(tctx, "Testing getgrnam: %s\n", name);
     209             : 
     210         124 :         errno = 0;
     211         124 :         grp = getgrnam(name);
     212         124 :         ret = errno;
     213         124 :         torture_assert(tctx, (grp != NULL), talloc_asprintf(tctx,
     214             :                        "getgrnam(%s) failed - %d - %s",
     215             :                        name, ret, strerror(ret)));
     216             : 
     217         124 :         print_group(grp);
     218             : 
     219         124 :         if (grp_p != NULL) {
     220         124 :                 torture_assert(tctx, copy_group(tctx, grp, grp_p), __location__);
     221             :         }
     222             : 
     223         124 :         return true;
     224             : }
     225             : 
     226         116 : static bool test_getgrnam_r(struct torture_context *tctx,
     227             :                             const char *name,
     228             :                             struct group *grp_p)
     229             : {
     230             :         struct group grp, *grpp;
     231             :         char buffer[4096];
     232             :         int ret;
     233             : 
     234         116 :         torture_comment(tctx, "Testing getgrnam_r: %s\n", name);
     235             : 
     236         116 :         ret = getgrnam_r(name, &grp, buffer, sizeof(buffer), &grpp);
     237         116 :         torture_assert(tctx, ret == 0, talloc_asprintf(tctx,
     238             :                        "getgrnam_r(%s) failed - %d - %s",
     239             :                        name, ret, strerror(ret)));
     240             : 
     241         116 :         print_group(&grp);
     242             : 
     243         116 :         if (grp_p != NULL) {
     244         116 :                 torture_assert(tctx, copy_group(tctx, &grp, grp_p), __location__);
     245             :         }
     246             : 
     247         116 :         return true;
     248             : }
     249             : 
     250             : 
     251         186 : static bool test_getgrgid(struct torture_context *tctx,
     252             :                           gid_t gid,
     253             :                           struct group *grp_p)
     254             : {
     255             :         struct group *grp;
     256             :         int ret;
     257             : 
     258         186 :         torture_comment(tctx, "Testing getgrgid: %lu\n", (unsigned long)gid);
     259             : 
     260         186 :         errno = 0;
     261         186 :         grp = getgrgid(gid);
     262         186 :         ret = errno;
     263         186 :         torture_assert(tctx, (grp != NULL), talloc_asprintf(tctx,
     264             :                        "getgrgid(%lu) failed - %d - %s",
     265             :                        (unsigned long)gid, ret, strerror(ret)));
     266             : 
     267         186 :         print_group(grp);
     268             : 
     269         186 :         if (grp_p != NULL) {
     270         116 :                 torture_assert(tctx, copy_group(tctx, grp, grp_p), __location__);
     271             :         }
     272             : 
     273         186 :         return true;
     274             : }
     275             : 
     276         116 : static bool test_getgrgid_r(struct torture_context *tctx,
     277             :                             gid_t gid,
     278             :                             struct group *grp_p)
     279             : {
     280             :         struct group grp, *grpp;
     281             :         char buffer[4096];
     282             :         int ret;
     283             : 
     284         116 :         torture_comment(tctx, "Testing getgrgid_r: %lu\n", (unsigned long)gid);
     285             : 
     286         116 :         ret = getgrgid_r(gid, &grp, buffer, sizeof(buffer), &grpp);
     287         116 :         torture_assert(tctx, ret == 0, talloc_asprintf(tctx,
     288             :                        "getgrgid_r(%lu) failed - %d - %s",
     289             :                        (unsigned long)gid, ret, strerror(ret)));
     290             : 
     291         116 :         print_group(&grp);
     292             : 
     293         116 :         if (grp_p != NULL) {
     294         116 :                 torture_assert(tctx, copy_group(tctx, &grp, grp_p), __location__);
     295             :         }
     296             : 
     297         116 :         return true;
     298             : }
     299             : 
     300           6 : static bool test_enum_passwd(struct torture_context *tctx,
     301             :                              struct passwd **pwd_array_p,
     302             :                              size_t *num_pwd_p)
     303             : {
     304             :         struct passwd *pwd;
     305           6 :         struct passwd *pwd_array = NULL;
     306           6 :         size_t num_pwd = 0;
     307             : 
     308           6 :         torture_comment(tctx, "Testing setpwent\n");
     309           6 :         setpwent();
     310             : 
     311         195 :         while ((pwd = getpwent()) != NULL) {
     312         186 :                 torture_comment(tctx, "Testing getpwent\n");
     313             : 
     314         186 :                 print_passwd(pwd);
     315         186 :                 if (pwd_array_p && num_pwd_p) {
     316         186 :                         pwd_array = talloc_realloc(tctx, pwd_array, struct passwd, num_pwd+1);
     317         186 :                         torture_assert(tctx, pwd_array, "out of memory");
     318         186 :                         copy_passwd(tctx, pwd, &pwd_array[num_pwd]);
     319         186 :                         num_pwd++;
     320             :                 }
     321             :         }
     322             : 
     323           6 :         torture_comment(tctx, "Testing endpwent\n");
     324           6 :         endpwent();
     325             : 
     326           6 :         if (pwd_array_p) {
     327           6 :                 *pwd_array_p = pwd_array;
     328             :         }
     329           6 :         if (num_pwd_p) {
     330           6 :                 *num_pwd_p = num_pwd;
     331             :         }
     332             : 
     333           6 :         return true;
     334             : }
     335             : 
     336           4 : static bool test_enum_r_passwd(struct torture_context *tctx,
     337             :                                struct passwd **pwd_array_p,
     338             :                                size_t *num_pwd_p)
     339             : {
     340             :         struct passwd pwd, *pwdp;
     341           4 :         struct passwd *pwd_array = NULL;
     342           4 :         size_t num_pwd = 0;
     343             :         char buffer[4096];
     344             :         int ret;
     345             : 
     346           4 :         torture_comment(tctx, "Testing setpwent\n");
     347           4 :         setpwent();
     348             : 
     349             : #ifdef HAVE_GETPWENT_R /* getpwent_r not supported on macOS */
     350             :         while (1) {
     351         190 :                 torture_comment(tctx, "Testing getpwent_r\n");
     352             : 
     353             : #ifdef SOLARIS_GETPWENT_R
     354             :                 ret = getpwent_r(&pwd, buffer, sizeof(buffer));
     355             : #else /* SOLARIS_GETPWENT_R */
     356         128 :                 ret = getpwent_r(&pwd, buffer, sizeof(buffer), &pwdp);
     357             : #endif /* SOLARIS_GETPWENT_R */
     358         128 :                 if (ret != 0) {
     359           4 :                         if (ret != ENOENT) {
     360           0 :                                 torture_comment(tctx, "got %d return code\n", ret);
     361             :                         }
     362           4 :                         break;
     363             :                 }
     364         124 :                 print_passwd(&pwd);
     365         124 :                 if (pwd_array_p && num_pwd_p) {
     366         124 :                         pwd_array = talloc_realloc(tctx, pwd_array, struct passwd, num_pwd+1);
     367         124 :                         torture_assert(tctx, pwd_array, "out of memory");
     368         124 :                         copy_passwd(tctx, &pwd, &pwd_array[num_pwd]);
     369         124 :                         num_pwd++;
     370             :                 }
     371             :         }
     372             : #endif /* getpwent_r not supported on macOS */
     373             : 
     374           4 :         torture_comment(tctx, "Testing endpwent\n");
     375           4 :         endpwent();
     376             : 
     377           4 :         if (pwd_array_p) {
     378           4 :                 *pwd_array_p = pwd_array;
     379             :         }
     380           4 :         if (num_pwd_p) {
     381           4 :                 *num_pwd_p = num_pwd;
     382             :         }
     383             : 
     384           4 :         return true;
     385             : }
     386             : 
     387         744 : static bool torture_assert_passwd_equal(struct torture_context *tctx,
     388             :                                         const struct passwd *p1,
     389             :                                         const struct passwd *p2,
     390             :                                         const char *comment)
     391             : {
     392         744 :         torture_assert_str_equal(tctx, p1->pw_name, p2->pw_name, comment);
     393         744 :         torture_assert_str_equal(tctx, p1->pw_passwd, p2->pw_passwd, comment);
     394         744 :         torture_assert_int_equal(tctx, p1->pw_uid, p2->pw_uid, comment);
     395         744 :         torture_assert_int_equal(tctx, p1->pw_gid, p2->pw_gid, comment);
     396         744 :         torture_assert_str_equal(tctx, p1->pw_gecos, p2->pw_gecos, comment);
     397         744 :         torture_assert_str_equal(tctx, p1->pw_dir, p2->pw_dir, comment);
     398         744 :         torture_assert_str_equal(tctx, p1->pw_shell, p2->pw_shell, comment);
     399             : 
     400         744 :         return true;
     401             : }
     402             : 
     403           2 : static bool test_passwd(struct torture_context *tctx)
     404             : {
     405             :         int i;
     406             :         struct passwd *pwd, pwd1, pwd2;
     407             :         size_t num_pwd;
     408             : 
     409           2 :         torture_assert(tctx, test_enum_passwd(tctx, &pwd, &num_pwd),
     410             :                                               "failed to enumerate passwd");
     411             : 
     412          64 :         for (i=0; i < num_pwd; i++) {
     413          62 :                 torture_assert(tctx, test_getpwnam(tctx, pwd[i].pw_name, &pwd1),
     414             :                         "failed to call getpwnam for enumerated user");
     415          62 :                 torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd[i], &pwd1,
     416             :                         "getpwent and getpwnam gave different results"),
     417             :                         __location__);
     418          62 :                 torture_assert(tctx, test_getpwuid(tctx, pwd[i].pw_uid, &pwd2),
     419             :                         "failed to call getpwuid for enumerated user");
     420          62 :                 torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd[i], &pwd2,
     421             :                         "getpwent and getpwuid gave different results"),
     422             :                         __location__);
     423          62 :                 torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd1, &pwd2,
     424             :                         "getpwnam and getpwuid gave different results"),
     425             :                         __location__);
     426             :         }
     427             : 
     428           2 :         return true;
     429             : }
     430             : 
     431           2 : static bool test_passwd_r(struct torture_context *tctx)
     432             : {
     433             :         int i;
     434             :         struct passwd *pwd, pwd1, pwd2;
     435             :         size_t num_pwd;
     436             : 
     437           2 :         torture_assert(tctx, test_enum_r_passwd(tctx, &pwd, &num_pwd),
     438             :                                                 "failed to enumerate passwd");
     439             : 
     440          64 :         for (i=0; i < num_pwd; i++) {
     441          62 :                 torture_assert(tctx, test_getpwnam_r(tctx, pwd[i].pw_name, &pwd1),
     442             :                         "failed to call getpwnam_r for enumerated user");
     443          62 :                 torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd[i], &pwd1,
     444             :                         "getpwent_r and getpwnam_r gave different results"),
     445             :                         __location__);
     446          62 :                 torture_assert(tctx, test_getpwuid_r(tctx, pwd[i].pw_uid, &pwd2),
     447             :                         "failed to call getpwuid_r for enumerated user");
     448          62 :                 torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd[i], &pwd2,
     449             :                         "getpwent_r and getpwuid_r gave different results"),
     450             :                         __location__);
     451          62 :                 torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd1, &pwd2,
     452             :                         "getpwnam_r and getpwuid_r gave different results"),
     453             :                         __location__);
     454             :         }
     455             : 
     456           2 :         return true;
     457             : }
     458             : 
     459           2 : static bool test_passwd_r_cross(struct torture_context *tctx)
     460             : {
     461             :         int i;
     462             :         struct passwd *pwd, pwd1, pwd2, pwd3, pwd4;
     463             :         size_t num_pwd;
     464             : 
     465           2 :         torture_assert(tctx, test_enum_r_passwd(tctx, &pwd, &num_pwd),
     466             :                                                 "failed to enumerate passwd");
     467             : 
     468          64 :         for (i=0; i < num_pwd; i++) {
     469          62 :                 torture_assert(tctx, test_getpwnam_r(tctx, pwd[i].pw_name, &pwd1),
     470             :                         "failed to call getpwnam_r for enumerated user");
     471          62 :                 torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd[i], &pwd1,
     472             :                         "getpwent_r and getpwnam_r gave different results"),
     473             :                         __location__);
     474          62 :                 torture_assert(tctx, test_getpwuid_r(tctx, pwd[i].pw_uid, &pwd2),
     475             :                         "failed to call getpwuid_r for enumerated user");
     476          62 :                 torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd[i], &pwd2,
     477             :                         "getpwent_r and getpwuid_r gave different results"),
     478             :                         __location__);
     479          62 :                 torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd1, &pwd2,
     480             :                         "getpwnam_r and getpwuid_r gave different results"),
     481             :                         __location__);
     482          62 :                 torture_assert(tctx, test_getpwnam(tctx, pwd[i].pw_name, &pwd3),
     483             :                         "failed to call getpwnam for enumerated user");
     484          62 :                 torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd[i], &pwd3,
     485             :                         "getpwent_r and getpwnam gave different results"),
     486             :                         __location__);
     487          62 :                 torture_assert(tctx, test_getpwuid(tctx, pwd[i].pw_uid, &pwd4),
     488             :                         "failed to call getpwuid for enumerated user");
     489          62 :                 torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd[i], &pwd4,
     490             :                         "getpwent_r and getpwuid gave different results"),
     491             :                         __location__);
     492          62 :                 torture_assert(tctx, torture_assert_passwd_equal(tctx, &pwd3, &pwd4,
     493             :                         "getpwnam and getpwuid gave different results"),
     494             :                         __location__);
     495             :         }
     496             : 
     497           2 :         return true;
     498             : }
     499             : 
     500           6 : static bool test_enum_group(struct torture_context *tctx,
     501             :                             struct group **grp_array_p,
     502             :                             size_t *num_grp_p)
     503             : {
     504             :         struct group *grp;
     505           6 :         struct group *grp_array = NULL;
     506           6 :         size_t num_grp = 0;
     507             : 
     508           6 :         torture_comment(tctx, "Testing setgrent\n");
     509           6 :         setgrent();
     510             : 
     511         183 :         while ((grp = getgrent()) != NULL) {
     512         174 :                 torture_comment(tctx, "Testing getgrent\n");
     513             : 
     514         174 :                 print_group(grp);
     515         174 :                 if (grp_array_p && num_grp_p) {
     516         174 :                         grp_array = talloc_realloc(tctx, grp_array, struct group, num_grp+1);
     517         174 :                         torture_assert(tctx, grp_array, "out of memory");
     518         174 :                         copy_group(tctx, grp, &grp_array[num_grp]);
     519         174 :                         num_grp++;
     520             :                 }
     521             :         }
     522             : 
     523           6 :         torture_comment(tctx, "Testing endgrent\n");
     524           6 :         endgrent();
     525             : 
     526           6 :         if (grp_array_p) {
     527           6 :                 *grp_array_p = grp_array;
     528             :         }
     529           6 :         if (num_grp_p) {
     530           6 :                 *num_grp_p = num_grp;
     531             :         }
     532             : 
     533           6 :         return true;
     534             : }
     535             : 
     536           4 : static bool test_enum_r_group(struct torture_context *tctx,
     537             :                               struct group **grp_array_p,
     538             :                               size_t *num_grp_p)
     539             : {
     540             :         struct group grp, *grpp;
     541           4 :         struct group *grp_array = NULL;
     542           4 :         size_t num_grp = 0;
     543             :         char buffer[4096];
     544             :         int ret;
     545             : 
     546           4 :         torture_comment(tctx, "Testing setgrent\n");
     547           4 :         setgrent();
     548             : 
     549             : #ifdef HAVE_GETGRENT_R /* getgrent_r not supported on macOS */
     550             :         while (1) {
     551         178 :                 torture_comment(tctx, "Testing getgrent_r\n");
     552             : 
     553             : #ifdef SOLARIS_GETGRENT_R
     554             :                 ret = getgrent_r(&grp, buffer, sizeof(buffer));
     555             : #else /* SOLARIS_GETGRENT_R */
     556         120 :                 ret = getgrent_r(&grp, buffer, sizeof(buffer), &grpp);
     557             : #endif /* SOLARIS_GETGRENT_R */
     558         120 :                 if (ret != 0) {
     559           4 :                         if (ret != ENOENT) {
     560           0 :                                 torture_comment(tctx, "got %d return code\n", ret);
     561             :                         }
     562           4 :                         break;
     563             :                 }
     564         116 :                 print_group(&grp);
     565         116 :                 if (grp_array_p && num_grp_p) {
     566         116 :                         grp_array = talloc_realloc(tctx, grp_array, struct group, num_grp+1);
     567         116 :                         torture_assert(tctx, grp_array, "out of memory");
     568         116 :                         copy_group(tctx, &grp, &grp_array[num_grp]);
     569         116 :                         num_grp++;
     570             :                 }
     571             :         }
     572             : #endif /* getgrent_r not supported on macOS */
     573             : 
     574           4 :         torture_comment(tctx, "Testing endgrent\n");
     575           4 :         endgrent();
     576             : 
     577           4 :         if (grp_array_p) {
     578           4 :                 *grp_array_p = grp_array;
     579             :         }
     580           4 :         if (num_grp_p) {
     581           4 :                 *num_grp_p = num_grp;
     582             :         }
     583             : 
     584           4 :         return true;
     585             : }
     586             : 
     587         696 : static bool torture_assert_group_equal(struct torture_context *tctx,
     588             :                                        const struct group *g1,
     589             :                                        const struct group *g2,
     590             :                                        const char *comment)
     591             : {
     592             :         int i;
     593         696 :         torture_assert_str_equal(tctx, g1->gr_name, g2->gr_name, comment);
     594         696 :         torture_assert_str_equal(tctx, g1->gr_passwd, g2->gr_passwd, comment);
     595         696 :         torture_assert_int_equal(tctx, g1->gr_gid, g2->gr_gid, comment);
     596         696 :         torture_assert(tctx, !(g1->gr_mem && !g2->gr_mem), __location__);
     597         696 :         torture_assert(tctx, !(!g1->gr_mem && g2->gr_mem), __location__);
     598         696 :         if (!g1->gr_mem && !g2->gr_mem) {
     599         600 :                 return true;
     600             :         }
     601         192 :         for (i=0; g1->gr_mem[i] && g2->gr_mem[i]; i++) {
     602          96 :                 torture_assert_str_equal(tctx, g1->gr_mem[i], g2->gr_mem[i], comment);
     603             :         }
     604             : 
     605          96 :         return true;
     606             : }
     607             : 
     608           2 : static bool test_group(struct torture_context *tctx)
     609             : {
     610             :         int i;
     611             :         struct group *grp, grp1, grp2;
     612             :         size_t num_grp;
     613             : 
     614           2 :         torture_assert(tctx, test_enum_group(tctx, &grp, &num_grp),
     615             :                                              "failed to enumerate group");
     616             : 
     617          60 :         for (i=0; i < num_grp; i++) {
     618          58 :                 torture_assert(tctx, test_getgrnam(tctx, grp[i].gr_name, &grp1),
     619             :                         "failed to call getgrnam for enumerated user");
     620          58 :                 torture_assert(tctx, torture_assert_group_equal(tctx, &grp[i], &grp1,
     621             :                         "getgrent and getgrnam gave different results"),
     622             :                         __location__);
     623          58 :                 torture_assert(tctx, test_getgrgid(tctx, grp[i].gr_gid, &grp2),
     624             :                         "failed to call getgrgid for enumerated user");
     625          58 :                 torture_assert(tctx, torture_assert_group_equal(tctx, &grp[i], &grp2,
     626             :                         "getgrent and getgrgid gave different results"),
     627             :                         __location__);
     628          58 :                 torture_assert(tctx, torture_assert_group_equal(tctx, &grp1, &grp2,
     629             :                         "getgrnam and getgrgid gave different results"),
     630             :                         __location__);
     631             :         }
     632             : 
     633           2 :         return true;
     634             : }
     635             : 
     636           2 : static bool test_group_r(struct torture_context *tctx)
     637             : {
     638             :         int i;
     639             :         struct group *grp, grp1, grp2;
     640             :         size_t num_grp;
     641             : 
     642           2 :         torture_assert(tctx, test_enum_r_group(tctx, &grp, &num_grp),
     643             :                                                "failed to enumerate group");
     644             : 
     645          60 :         for (i=0; i < num_grp; i++) {
     646          58 :                 torture_assert(tctx, test_getgrnam_r(tctx, grp[i].gr_name, &grp1),
     647             :                         "failed to call getgrnam_r for enumerated user");
     648          58 :                 torture_assert(tctx, torture_assert_group_equal(tctx, &grp[i], &grp1,
     649             :                         "getgrent_r and getgrnam_r gave different results"),
     650             :                         __location__);
     651          58 :                 torture_assert(tctx, test_getgrgid_r(tctx, grp[i].gr_gid, &grp2),
     652             :                         "failed to call getgrgid_r for enumerated user");
     653          58 :                 torture_assert(tctx, torture_assert_group_equal(tctx, &grp[i], &grp2,
     654             :                         "getgrent_r and getgrgid_r gave different results"),
     655             :                         __location__);
     656          58 :                 torture_assert(tctx, torture_assert_group_equal(tctx, &grp1, &grp2,
     657             :                         "getgrnam_r and getgrgid_r gave different results"),
     658             :                         __location__);
     659             :         }
     660             : 
     661           2 :         return true;
     662             : }
     663             : 
     664           2 : static bool test_group_r_cross(struct torture_context *tctx)
     665             : {
     666             :         int i;
     667             :         struct group *grp, grp1, grp2, grp3, grp4;
     668             :         size_t num_grp;
     669             : 
     670           2 :         torture_assert(tctx, test_enum_r_group(tctx, &grp, &num_grp),
     671             :                                                "failed to enumerate group");
     672             : 
     673          60 :         for (i=0; i < num_grp; i++) {
     674          58 :                 torture_assert(tctx, test_getgrnam_r(tctx, grp[i].gr_name, &grp1),
     675             :                         "failed to call getgrnam_r for enumerated user");
     676          58 :                 torture_assert(tctx, torture_assert_group_equal(tctx, &grp[i], &grp1,
     677             :                         "getgrent_r and getgrnam_r gave different results"),
     678             :                         __location__);
     679          58 :                 torture_assert(tctx, test_getgrgid_r(tctx, grp[i].gr_gid, &grp2),
     680             :                         "failed to call getgrgid_r for enumerated user");
     681          58 :                 torture_assert(tctx, torture_assert_group_equal(tctx, &grp[i], &grp2,
     682             :                         "getgrent_r and getgrgid_r gave different results"),
     683             :                         __location__);
     684          58 :                 torture_assert(tctx, torture_assert_group_equal(tctx, &grp1, &grp2,
     685             :                         "getgrnam_r and getgrgid_r gave different results"),
     686             :                         __location__);
     687          58 :                 torture_assert(tctx, test_getgrnam(tctx, grp[i].gr_name, &grp3),
     688             :                         "failed to call getgrnam for enumerated user");
     689          58 :                 torture_assert(tctx, torture_assert_group_equal(tctx, &grp[i], &grp3,
     690             :                         "getgrent_r and getgrnam gave different results"),
     691             :                         __location__);
     692          58 :                 torture_assert(tctx, test_getgrgid(tctx, grp[i].gr_gid, &grp4),
     693             :                         "failed to call getgrgid for enumerated user");
     694          58 :                 torture_assert(tctx, torture_assert_group_equal(tctx, &grp[i], &grp4,
     695             :                         "getgrent_r and getgrgid gave different results"),
     696             :                         __location__);
     697          58 :                 torture_assert(tctx, torture_assert_group_equal(tctx, &grp3, &grp4,
     698             :                         "getgrnam and getgrgid gave different results"),
     699             :                         __location__);
     700             :         }
     701             : 
     702           2 :         return true;
     703             : }
     704             : 
     705             : #ifdef HAVE_GETGROUPLIST
     706          62 : static bool test_getgrouplist(struct torture_context *tctx,
     707             :                               const char *user,
     708             :                               gid_t gid,
     709             :                               gid_t **gids_p,
     710             :                               int *num_gids_p)
     711             : {
     712             :         int ret;
     713          62 :         int num_groups = 0;
     714          62 :         gid_t *groups = NULL;
     715             : 
     716          62 :         torture_comment(tctx, "Testing getgrouplist: %s\n", user);
     717             : 
     718          62 :         ret = getgrouplist(user, gid, NULL, &num_groups);
     719          62 :         if (ret == -1 || num_groups != 0) {
     720             : 
     721          62 :                 groups = talloc_array(tctx, gid_t, num_groups);
     722          62 :                 torture_assert(tctx, groups, "out of memory\n");
     723             : 
     724          62 :                 ret = getgrouplist(user, gid, groups, &num_groups);
     725             :         }
     726             : 
     727          62 :         torture_assert(tctx, (ret != -1), "failed to call getgrouplist");
     728             : 
     729          62 :         torture_comment(tctx, "%s is member in %d groups\n", user, num_groups);
     730             : 
     731          62 :         if (gids_p) {
     732          62 :                 *gids_p = groups;
     733             :         }
     734          62 :         if (num_gids_p) {
     735          62 :                 *num_gids_p = num_groups;
     736             :         }
     737             : 
     738          62 :         return true;
     739             : }
     740             : #endif /* HAVE_GETGROUPLIST */
     741             : 
     742        1798 : static bool test_user_in_group(struct torture_context *tctx,
     743             :                                const struct passwd *pwd,
     744             :                                const struct group *grp)
     745             : {
     746             :         int i;
     747             : 
     748        2038 :         for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) {
     749         248 :                 if (strequal(grp->gr_mem[i], pwd->pw_name)) {
     750           8 :                         return true;
     751             :                 }
     752             :         }
     753             : 
     754        1790 :         return false;
     755             : }
     756             : 
     757          62 : static bool test_membership_user(struct torture_context *tctx,
     758             :                                  const struct passwd *pwd,
     759             :                                  struct group *grp_array,
     760             :                                  size_t num_grp)
     761             : {
     762          62 :         int num_user_groups = 0;
     763          62 :         int num_user_groups_from_enum = 0;
     764          62 :         gid_t *user_groups = NULL;
     765             :         int g, i;
     766          62 :         bool primary_group_had_user_member = false;
     767             : 
     768             : #ifdef HAVE_GETGROUPLIST
     769          62 :         torture_assert(tctx, test_getgrouplist(tctx,
     770             :                                                pwd->pw_name,
     771             :                                                pwd->pw_gid,
     772             :                                                &user_groups,
     773             :                                                &num_user_groups),
     774             :                                                "failed to test getgrouplist");
     775             : #endif /* HAVE_GETGROUPLIST */
     776             : 
     777         132 :         for (g=0; g < num_user_groups; g++) {
     778          70 :                 torture_assert(tctx, test_getgrgid(tctx, user_groups[g], NULL),
     779             :                         "failed to find the group the user is a member of");
     780             :         }
     781             : 
     782             : 
     783        1860 :         for (i=0; i < num_grp; i++) {
     784             : 
     785        1798 :                 struct group grp = grp_array[i];
     786             : 
     787        1798 :                 if (test_user_in_group(tctx, pwd, &grp)) {
     788             : 
     789             :                         struct group current_grp;
     790           8 :                         num_user_groups_from_enum++;
     791             : 
     792           8 :                         torture_assert(tctx, test_getgrnam(tctx, grp.gr_name, &current_grp),
     793             :                                         "failed to find the group the user is a member of");
     794             : 
     795           8 :                         if (current_grp.gr_gid == pwd->pw_gid) {
     796           0 :                                 torture_comment(tctx, "primary group %s of user %s lists user as member\n",
     797             :                                                 current_grp.gr_name,
     798           0 :                                                 pwd->pw_name);
     799           0 :                                 primary_group_had_user_member = true;
     800             :                         }
     801             : 
     802           8 :                         continue;
     803             :                 }
     804             :         }
     805             : 
     806          62 :         if (!primary_group_had_user_member) {
     807          62 :                 num_user_groups_from_enum++;
     808             :         }
     809             : 
     810          62 :         torture_assert_int_equal(tctx, num_user_groups, num_user_groups_from_enum,
     811             :                 "getgrouplist and real inspection of grouplist gave different results\n");
     812             : 
     813          62 :         return true;
     814             : }
     815             : 
     816           2 : static bool test_membership(struct torture_context *tctx)
     817             : {
     818           2 :         const char *old_pwd = getenv("NSS_WRAPPER_PASSWD");
     819           2 :         const char *old_group = getenv("NSS_WRAPPER_GROUP");
     820             :         struct passwd *pwd;
     821             :         size_t num_pwd;
     822             :         struct group *grp;
     823             :         size_t num_grp;
     824             :         int i;
     825             : 
     826           2 :         if (!old_pwd || !old_group) {
     827           0 :                 torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n");
     828           0 :                 torture_skip(tctx, "nothing to test\n");
     829             :         }
     830             : 
     831           2 :         torture_assert(tctx, test_enum_passwd(tctx, &pwd, &num_pwd),
     832             :                                               "failed to enumerate passwd");
     833           2 :         torture_assert(tctx, test_enum_group(tctx, &grp, &num_grp),
     834             :                                              "failed to enumerate group");
     835             : 
     836          64 :         for (i=0; i < num_pwd; i++) {
     837             : 
     838          62 :                 torture_assert(tctx, test_membership_user(tctx, &pwd[i], grp, num_grp),
     839             :                         "failed to test membership for user");
     840             : 
     841             :         }
     842             : 
     843           2 :         return true;
     844             : }
     845             : 
     846           2 : static bool test_enumeration(struct torture_context *tctx)
     847             : {
     848           2 :         const char *old_pwd = getenv("NSS_WRAPPER_PASSWD");
     849           2 :         const char *old_group = getenv("NSS_WRAPPER_GROUP");
     850             : 
     851           2 :         if (!old_pwd || !old_group) {
     852           0 :                 torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n");
     853           0 :                 torture_skip(tctx, "nothing to test\n");
     854             :         }
     855             : 
     856           2 :         torture_assert(tctx, test_passwd(tctx),
     857             :                         "failed to test users");
     858           2 :         torture_assert(tctx, test_group(tctx),
     859             :                         "failed to test groups");
     860             : 
     861           2 :         return true;
     862             : }
     863             : 
     864           2 : static bool test_reentrant_enumeration(struct torture_context *tctx)
     865             : {
     866           2 :         const char *old_pwd = getenv("NSS_WRAPPER_PASSWD");
     867           2 :         const char *old_group = getenv("NSS_WRAPPER_GROUP");
     868             : 
     869           2 :         if (!old_pwd || !old_group) {
     870           0 :                 torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n");
     871           0 :                 torture_skip(tctx, "nothing to test\n");
     872             :         }
     873             : 
     874           2 :         torture_comment(tctx, "Testing re-entrant calls\n");
     875             : 
     876           2 :         torture_assert(tctx, test_passwd_r(tctx),
     877             :                         "failed to test users");
     878           2 :         torture_assert(tctx, test_group_r(tctx),
     879             :                         "failed to test groups");
     880             : 
     881           2 :         return true;
     882             : }
     883             : 
     884           2 : static bool test_reentrant_enumeration_crosschecks(struct torture_context *tctx)
     885             : {
     886           2 :         const char *old_pwd = getenv("NSS_WRAPPER_PASSWD");
     887           2 :         const char *old_group = getenv("NSS_WRAPPER_GROUP");
     888             : 
     889           2 :         if (!old_pwd || !old_group) {
     890           0 :                 torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n");
     891           0 :                 torture_skip(tctx, "nothing to test\n");
     892             :         }
     893             : 
     894           2 :         torture_comment(tctx, "Testing re-entrant calls with cross checks\n");
     895             : 
     896           2 :         torture_assert(tctx, test_passwd_r_cross(tctx),
     897             :                         "failed to test users");
     898           2 :         torture_assert(tctx, test_group_r_cross(tctx),
     899             :                         "failed to test groups");
     900             : 
     901           2 :         return true;
     902             : }
     903             : 
     904           2 : static bool test_passwd_duplicates(struct torture_context *tctx)
     905             : {
     906             :         size_t i, d;
     907             :         struct passwd *pwd;
     908             :         size_t num_pwd;
     909           2 :         int duplicates = 0;
     910             : 
     911           2 :         torture_assert(tctx, test_enum_passwd(tctx, &pwd, &num_pwd),
     912             :             "failed to enumerate passwd");
     913             : 
     914          64 :         for (i=0; i < num_pwd; i++) {
     915          62 :                 const char *current_name = pwd[i].pw_name;
     916        1984 :                 for (d=0; d < num_pwd; d++) {
     917        1922 :                         const char *dup_name = pwd[d].pw_name;
     918        1922 :                         if (d == i) {
     919          62 :                                 continue;
     920             :                         }
     921        1860 :                         if (!strequal(current_name, dup_name)) {
     922        1860 :                                 continue;
     923             :                         }
     924             : 
     925           0 :                         torture_warning(tctx, "found duplicate names:");
     926           0 :                         print_passwd(&pwd[d]);
     927           0 :                         print_passwd(&pwd[i]);
     928           0 :                         duplicates++;
     929             :                 }
     930             :         }
     931             : 
     932           2 :         if (duplicates) {
     933           0 :                 torture_fail(tctx, talloc_asprintf(tctx, "found %d duplicate names", duplicates));
     934             :         }
     935             : 
     936           2 :         return true;
     937             : }
     938             : 
     939           2 : static bool test_group_duplicates(struct torture_context *tctx)
     940             : {
     941             :         size_t i, d;
     942             :         struct group *grp;
     943             :         size_t num_grp;
     944           2 :         int duplicates = 0;
     945             : 
     946           2 :         torture_assert(tctx, test_enum_group(tctx, &grp, &num_grp),
     947             :                 "failed to enumerate group");
     948             : 
     949          60 :         for (i=0; i < num_grp; i++) {
     950          58 :                 const char *current_name = grp[i].gr_name;
     951        1740 :                 for (d=0; d < num_grp; d++) {
     952        1682 :                         const char *dup_name = grp[d].gr_name;
     953        1682 :                         if (d == i) {
     954          58 :                                 continue;
     955             :                         }
     956        1624 :                         if (!strequal(current_name, dup_name)) {
     957        1624 :                                 continue;
     958             :                         }
     959             : 
     960           0 :                         torture_warning(tctx, "found duplicate names:");
     961           0 :                         print_group(&grp[d]);
     962           0 :                         print_group(&grp[i]);
     963           0 :                         duplicates++;
     964             :                 }
     965             :         }
     966             : 
     967           2 :         if (duplicates) {
     968           0 :                 torture_fail(tctx, talloc_asprintf(tctx, "found %d duplicate names", duplicates));
     969             :         }
     970             : 
     971           2 :         return true;
     972             : }
     973             : 
     974             : 
     975           2 : static bool test_duplicates(struct torture_context *tctx)
     976             : {
     977           2 :         const char *old_pwd = getenv("NSS_WRAPPER_PASSWD");
     978           2 :         const char *old_group = getenv("NSS_WRAPPER_GROUP");
     979             : 
     980           2 :         if (!old_pwd || !old_group) {
     981           0 :                 torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n");
     982           0 :                 torture_skip(tctx, "nothing to test\n");
     983             :         }
     984             : 
     985           2 :         torture_assert(tctx, test_passwd_duplicates(tctx),
     986             :                         "failed to test users");
     987           2 :         torture_assert(tctx, test_group_duplicates(tctx),
     988             :                         "failed to test groups");
     989             : 
     990           2 :         return true;
     991             : }
     992             : 
     993             : 
     994         964 : struct torture_suite *torture_local_nss(TALLOC_CTX *mem_ctx)
     995             : {
     996         964 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "nss");
     997             : 
     998         964 :         torture_suite_add_simple_test(suite, "enumeration", test_enumeration);
     999         964 :         torture_suite_add_simple_test(suite, "reentrant enumeration", test_reentrant_enumeration);
    1000         964 :         torture_suite_add_simple_test(suite, "reentrant enumeration crosschecks", test_reentrant_enumeration_crosschecks);
    1001         964 :         torture_suite_add_simple_test(suite, "membership", test_membership);
    1002         964 :         torture_suite_add_simple_test(suite, "duplicates", test_duplicates);
    1003             : 
    1004         964 :         return suite;
    1005             : }

Generated by: LCOV version 1.13