@@ -25,6 +25,7 @@ The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
2525#include <sys/file.h>
2626#include <regex.h>
2727#include <time.h>
28+ #include <sys/wait.h>
2829
2930#include "nss_radius_common.h"
3031
@@ -167,6 +168,124 @@ static void init_rnm(RADIUS_NSS_CONF_B * conf) {
167168
168169}
169170
171+ static int user_add (const char * name , char * gid , char * sec_grp , char * gecos ,
172+ char * home , char * shell , const char * unconfirmed_user , int many_to_one ) {
173+ pid_t pid , w ;
174+ int status = 0 ;
175+ int wstatus ;
176+ char cmd [64 ];
177+
178+ snprintf (cmd , 63 , "%s" , USERADD );
179+
180+ pid = fork ();
181+
182+ if (pid > 0 ) {
183+ do {
184+ w = waitpid (pid , & wstatus , WUNTRACED | WCONTINUED );
185+ if (w == -1 )
186+ return -1 ;
187+ } while (!WIFEXITED (wstatus ) && !WIFSIGNALED (wstatus ));
188+ if WIFEXITED (wstatus )
189+ return WEXITSTATUS (wstatus );
190+ else
191+ return -1 ;
192+
193+ // Child
194+
195+ } else if (pid == 0 ) {
196+
197+ if (many_to_one )
198+ execl (cmd , cmd , "-g" , gid , "-G" , sec_grp , "-c" , gecos , "-m" , "-s" , shell , name , NULL );
199+ else
200+ execl (cmd , cmd , "-U" , "-G" , sec_grp , "-c" , unconfirmed_user , "-d" , home , "-m" , "-s" , shell , name , NULL );
201+ syslog (LOG_ERR , "exec of %s failed with errno=%d" , cmd , errno );
202+ return -1 ;
203+
204+ // Error
205+ } else {
206+ fprintf (stderr , "error forking the child\n" );
207+ return -1 ;
208+ }
209+
210+ return status ;
211+ }
212+
213+ static int user_del (const char * name ) {
214+ pid_t pid , w ;
215+ int status = 0 ;
216+ int wstatus ;
217+ char cmd [64 ];
218+
219+ snprintf (cmd , 63 , "%s" , USERDEL );
220+
221+ pid = fork ();
222+
223+ if (pid > 0 ) {
224+ do {
225+ w = waitpid (pid , & wstatus , WUNTRACED | WCONTINUED );
226+ if (w == -1 )
227+ return -1 ;
228+ } while (!WIFEXITED (wstatus ) && !WIFSIGNALED (wstatus ));
229+ if WIFEXITED (wstatus )
230+ return WEXITSTATUS (wstatus );
231+ else
232+ return -1 ;
233+
234+ // Child
235+
236+ } else if (pid == 0 ) {
237+
238+ execl (cmd , cmd , "-r" , name , NULL );
239+ syslog (LOG_ERR , "exec of %s failed with errno=%d" , cmd , errno );
240+ return -1 ;
241+
242+ // Error
243+ } else {
244+ fprintf (stderr , "error forking the child\n" );
245+ return -1 ;
246+ }
247+
248+ return status ;
249+ }
250+
251+ static int user_mod (const char * name , char * sec_grp ) {
252+ pid_t pid , w ;
253+ int status = 0 ;
254+ int wstatus ;
255+ char cmd [64 ];
256+
257+ snprintf (cmd , 63 , "%s" , USERMOD );
258+
259+ pid = fork ();
260+
261+ if (pid > 0 ) {
262+ do {
263+ w = waitpid (pid , & wstatus , WUNTRACED | WCONTINUED );
264+ if (w == -1 )
265+ return -1 ;
266+ } while (!WIFEXITED (wstatus ) && !WIFSIGNALED (wstatus ));
267+ if WIFEXITED (wstatus )
268+ return WEXITSTATUS (wstatus );
269+ else
270+ return -1 ;
271+
272+ // Child
273+
274+ } else if (pid == 0 ) {
275+
276+ execl (cmd , cmd , "-G" , sec_grp , "-c" , name , name , NULL );
277+ syslog (LOG_ERR , "exec of %s failed with errno=%d" , cmd , errno );
278+ return -1 ;
279+
280+ // Error
281+ } else {
282+ fprintf (stderr , "error forking the child\n" );
283+ return -1 ;
284+ }
285+
286+ return status ;
287+ }
288+
170289int parse_nss_config (RADIUS_NSS_CONF_B * conf , char * prog ,
171290 char * file_buf , int file_buf_sz , int * errnop , int * plockfd ) {
172291
@@ -379,22 +498,6 @@ int unparse_nss_config(RADIUS_NSS_CONF_B * conf, int * errnop, int * plockfd) {
379498 return 0 ;
380499}
381500
382- static int invoke_popen (RADIUS_NSS_CONF_B * conf , char * cmd ) {
383- FILE * fp ;
384- int status = 0 ;
385-
386- if (conf -> debug )
387- syslog (LOG_DEBUG , "%s:%s" , conf -> prog , cmd );
388-
389- if (((fp = popen (cmd , "r" )) == NULL ) || (pclose (fp ) == -1 )) {
390- syslog (LOG_ERR , "%s: %s: popen()/pclose() failed %p, errno=%d" ,
391- conf -> prog , cmd , fp , errno );
392- status = errno ;
393- }
394-
395- return status ;
396- }
397-
398501static int radius_getpwnam_r_cleanup (int status , FILE * fp ) {
399502 if (fp )
400503 fclose (fp );
@@ -434,10 +537,8 @@ static int radius_update_user_cleanup(int status) {
434537int radius_update_user (RADIUS_NSS_CONF_B * conf , const char * user , int mpl ) {
435538
436539 char buf [BUFLEN ];
437- char usermod [4096 ];
438540 struct passwd pw , * result = NULL ;
439541 RADIUS_NSS_MPL * rnm = NULL ;
440- int written = 0 ;
441542 int status ;
442543
443544 /* Verify uid is not in the reserved range (<=1000).
@@ -466,82 +567,53 @@ int radius_update_user(RADIUS_NSS_CONF_B * conf, const char * user, int mpl) {
466567 if (conf -> trace )
467568 dump_rnm (mpl , rnm , "update" );
468569
469- written = snprintf (usermod , sizeof (usermod ),
470- "%s -G %s -c \"%s\" \"%s\"" , USERMOD , rnm -> groups , user , user );
471-
472- if (written >= sizeof (usermod )) {
473- syslog (LOG_ERR ,
474- "%s: truncated usermod cmd. Skipping:\"%s\"\n" , conf -> prog , usermod );
475- return radius_update_user_cleanup (STATUS_E2BIG );
570+ if (0 != user_mod (user , rnm -> groups )) {
571+ syslog (LOG_ERR , "%s: %s %s failed" , conf -> prog , USERMOD , user );
572+ return -1 ;
476573 }
477-
478- return radius_update_user_cleanup (invoke_popen (conf , usermod ));
479- }
480-
481- static int radius_create_user_cleanup (int status ) {
482- return status ;
574+ return 0 ;
483575}
484576
485577int radius_create_user (RADIUS_NSS_CONF_B * conf , const char * user , int mpl ,
486578 int unconfirmed ) {
487579
488- char buf [BUFLEN ];
489- char useradd [4096 ];
580+ char buf [BUFLEN ] = {0 };
490581 RADIUS_NSS_MPL * rnm = & ((conf -> rnm )[mpl - 1 ]);
491- int written = 0 ;
492582
493583 if (conf -> trace )
494584 dump_rnm (mpl , rnm , "create" );
495585
586+ if (strlen (user ) > 32 ) {
587+ syslog (LOG_ERR , "%s: Username too long" , conf -> prog );
588+ return -1 ;
589+ }
496590
497- if ( conf -> many_to_one ) {
591+ syslog ( LOG_INFO , "%s: Creating user \"%s\"" , conf -> prog , user );
498592
499- written = snprintf (useradd , sizeof (useradd ),
500- "%s -g %d -G %s -c \"%s\" -m -s %s \"%s\"" ,
501- USERADD , rnm -> gid , rnm -> groups , rnm -> gecos , rnm -> shell , user );
593+ char sgid [10 ] = {0 };
594+ char home [64 ] = {0 };
595+ snprintf (sgid , 10 , "%d" , rnm -> gid );
596+ snprintf (home , 63 , "/home/%s" , user );
502597
503- } else {
598+ snprintf ( buf , sizeof ( buf ), "Unconfirmed-%ld" , time ( NULL ));
504599
505- snprintf (buf , sizeof (buf ), "Unconfirmed-%ld" , time (NULL ));
506- written = snprintf (useradd , sizeof (useradd ),
507- "%s -U -G %s -c \"%s\" -d \"/home/%s\" -m -s %s \"%s\"" ,
508- USERADD , rnm -> groups , unconfirmed ? buf : user , user ,
509- rnm -> shell , user );
510-
511- }
600+ if (0 != user_add (user , sgid , rnm -> groups , rnm -> gecos , home , rnm -> shell , unconfirmed ? buf : user , conf -> many_to_one )) {
601+ syslog (LOG_ERR , "%s: %s %s failed" , conf -> prog , USERADD , user );
512602
513- if (written >= sizeof (useradd )) {
514- syslog (LOG_ERR ,
515- "%s: truncated useradd cmd. Skipping:\"%s\"\n" , conf -> prog , useradd );
516- return radius_create_user_cleanup (STATUS_E2BIG );
603+ return -1 ;
517604 }
518-
519- syslog (LOG_INFO , "%s: Creating user \"%s\"" , conf -> prog , user );
520-
521- return radius_create_user_cleanup (invoke_popen (conf , useradd ));
522- }
523-
524- static int radius_delete_user_cleanup (int status ) {
525- return status ;
605+ return 0 ;
526606}
527607
528608int radius_delete_user (RADIUS_NSS_CONF_B * conf , const char * user ) {
529609
530- char buf [BUFLEN ];
531- char userdel [4096 ];
532- int written = 0 ;
533-
534- written = snprintf (userdel , sizeof (userdel ), "%s -r \"%s\"" , USERDEL , user );
535-
536- if (written >= sizeof (userdel )) {
537- syslog (LOG_ERR ,
538- "%s: truncated userdel cmd. Skipping:\"%s\"\n" , conf -> prog , userdel );
539- return radius_delete_user_cleanup (STATUS_E2BIG );
540- }
541-
542610 syslog (LOG_INFO , "%s: Deleting user \"%s\"" , conf -> prog , user );
611+ if (0 != user_del (user )) {
612+ syslog (LOG_ERR , "%s: %s %s failed" , conf -> prog , USERDEL , user );
543613
544- return radius_delete_user_cleanup (invoke_popen (conf , userdel ));
614+ return -1 ;
615+ }
616+ return 0 ;
545617}
546618
547619int radius_clear_unconfirmed_users_cleanup (int status , FILE * fp ) {
0 commit comments