koryw has asked for the wisdom of the Perl Monks concerning the following question:

Do any of you have a good C wrapper program that checks two agrument values syntax, to make sure they are just characters, and then these agruments are passed to a perl script. This Perl script sets the effective UID, "which is root" and then it untaints the agruments so that it can be run as suid.

The C wrapper and everything else works fine, but I want to be able to check the syntax of the two agruments in C, before they are passed to the perl script, and I'm not sure how to do that.

Here's my C wrapper
* * ldap-group.c by Kory Wheatley * Idaho State University * September 29, 2003 * This is an suid wrapper for the ldapgroup program. */ #include <stdio.h> #include <string.h> #include <unistd.h> /* for exec */ main(argc, argv) int argc; char *argv []; { /* Make sure at least one argument is passed to this program */ if (argc < 2) { printf ("Usage: ldap-group [-p] trans \n"); exit(1); } /* execute the perl script */ execv("/opt/bin/techweb-changes.pl",argv); } /* END OF MAIN PROGRAM */

edited: Mon Sep 29 22:37:22 2003 by jeffa - code tags, p tags

Replies are listed 'Best First'.
Re: passing c agruments to Perl
by tachyon (Chancellor) on Sep 30, 2003 at 00:32 UTC

    Presumably you want to do this to avoid suid script restrictions. Here are a couple of options.

    #!/usr/bin/perl die Usage: ldap-group [-p] trans \n" unless @ARGV; for my $arg(@ARGV) { die "Invalid $arg\n" unless $arg =~ m/^[A-Za-z]+$/; } exec("/opt/bin/techweb-changes.pl",@ARGV);

    To do it in C it would be easiest to use a regex library

    #include <regex.h> /* * Match string against the extended regular expression in * pattern, treating errors as no match. * * return 1 for match, 0 for no match */ int match(const char *string, char *pattern) { int status; regex_t re; if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB) != 0) { return(0); /* report error */ } status = regexec(&re, string, (size_t) 0, NULL, 0); regfree(&re); if (status != 0) { return(0); /* report error */ } return(1); }

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

      I apologize I'm not following your C script very well, I used to be good in C, but I haven't used it for about 3 years. Could you make the script easier to understand.

        Its not a script, it is a single function called match() You pass match two arguments - one is the string you want to check, the other the regex patern you want that string to match. The regex pattern is shown in the Perl example. The function returns 1 if it matches. I don't know how it could be simpler.

        [root@devel3 root]# cat test.c #include <stdio.h> #include <regex.h> int main(int argc, char *argv[]) { int i; char *pat = "^[A-Z]+$"; printf("Got %d args\n", argc-1 ); /* first arg prog name */ for( i=1; i<argc; i++ ) { printf("Got %s\n",argv[i]); if ( match( argv[i], pat ) ) { printf("-->Match %s\n", pat); } else { printf("***Fail\n"); } } return 0; } int match(const char *string, char *pattern) { int status; regex_t re; if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB) != 0) { return(0); /* report error */ } status = regexec(&re, string, (size_t) 0, NULL, 0); regfree(&re); if (status != 0) { return(0); /* report error */ } return(1); } [root@devel3 root]# gcc test.c [root@devel3 root]# ./a.out 123 ABC abc ABC123 Got 4 args Got 123 ***Fail Got ABC -->Match ^[A-Z]+$ Got abc ***Fail Got ABC123 ***Fail [root@devel3 root]#

        I have no comprehension why you want to do data validation in C before you call a Perl script. Surely the Perl does data validation????? If so just use your C wrapper to exec the Perl script. End of story.

        cheers

        tachyon

        s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: passing c agruments to Perl
by BUU (Prior) on Sep 29, 2003 at 22:44 UTC
    Why on earth do you want to write a C wrapper to check args to perl?!
      Because of security, my Perl will be ran has root so I'm using C to put a security blanket around it. In the perl script of change to the Effective UID which is root.
        Either use the setuid function of POSIX, or else study perlvar for $< and $>, which can be used to change the real and effective UIDs in Perl itself, eliminating the need for a C wrapper.

        Even if it didn't have that built in, you could plan on using Inline::C to get access to useful C functionality directly in Perl.

        Remember that Perl has had a long life as a system administration tool on *nix, so you should expect that it has features which are useful for that, you just have to look for them.