sur.c #1

  • //
  • guest/
  • netapp/
  • p4flex/
  • main/
  • demo/
  • sur.c
  • View
  • Commits
  • Open Download .zip Download (7 KB)
/*
################################################################################
# CodeEasy Customer Toolkit Script
#          This script was developed by NetApp to help demonstrate NetApp 
#          technologies.  This script is not officially supported as a 
#          standard NetApp product.
#         
# Purpose: 
#          This program performs runs a command line as a new user, such
#          as a devops or build user who has permissions to do things
#          like create snapshot, create flexclones, etc.
#
#          [SEE BELOW FOR 'setuid' manpage]      
# 
#
# Usage:   %> sur <sur_dispatch_exe> <super username> <command line to execute>
#
# Author:  Michael Johnson (michael.johnson@netapp.com)
#
#
# NETAPP CONFIDENTIAL
# -------------------
# Copyright 2015 NetApp, Inc. All Rights Reserved.
#
# NOTICE: All information contained herein is, and remains the property
# of NetApp, Inc.  The intellectual and technical concepts contained
# herein are proprietary to NetApp, Inc. and its suppliers, if applicable,
# and may be covered by U.S. and Foreign Patents, patents in process, and are
# protected by trade secret or copyright law. Dissemination of this
# information or reproduction of this material is strictly forbidden unless
# permission is obtained from NetApp, Inc.
#
################################################################################
*/

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <libgen.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>

main (int argc, char ** argv) {
    int    id;
    char * sur_dispatch_exe;
    char * suser;
    int    suid;
    struct passwd * pw;
    int ix;
    

    // check that minimum number of command line arguments were passed
    if (argc <= 3) {
        fprintf(stderr, "\nERROR (%s): Invalid number of arguments.\n",       argv[0]);
	fprintf(stderr,   "        Usage:  \%> %s <username> <sur_dispatch cmd>  <cmdline to execute>\n\n", argv[0]);
	fprintf(stderr,   "      Example:  \%> %s /codeeasy_path/bin/sur devops 'CeChownList.pl -d <dir> -u <user> ' \n", argv[0]);
	fprintf(stderr,   "                will perform the equivalent of \%> chown <user>:<unchanged> file1 file2 file3\n\n");     
	exit(1);
    }

    // capture command line values 
    suser            = argv[1];
    sur_dispatch_exe = argv[2];  

    //-------------------------------------- 
    // determine new user id and then switch process id
    //-------------------------------------- 

    // Try getting UID from username passed from the cmd line
    pw = getpwnam (suser);
    if (pw == NULL) {
        fprintf (stderr, "\nERROR (%s): Failed to get UID for USER '%s'\n", argv[0], suser);
        fprintf (stderr,   "      Check that username exists.\n\n");
        exit (1);
    }

    // apply the uid
    suid = pw->pw_uid;
    fprintf(stdout, "INFO  (%s): Username '%s' converted to UID '%d' \n", argv[0], suser, suid);

    // set the new uid - all child processes will be run as the user with the new uid
    setuid (suid);

    // check that the new uid was actually set properly
    id = getuid ();
    if (id != suid) {
        fprintf (stderr, "ERROR (%s): Sur command failed to set UID to %d\n", argv[0], suid);
        exit (1);
    }

    //-------------------------------------- 
    // check that the sur_dispatch_exe is found and is executable
    //-------------------------------------- 
    if (access (sur_dispatch_exe, F_OK) == 0) {
        fprintf(stdout, "INFO  (%s): sur_dispatch_cmd = %s\n", argv[0], sur_dispatch_exe);
    } else {
        fprintf(stdout, "ERROR (%s): sur_dispatch_cmd '%s' not found.\n       %s\n", argv[0], sur_dispatch_exe);
	// Now perform the lchown operation
	exit(1);
    }

    //-------------------------------------- 
    // execute command with new uid
    //-------------------------------------- 
    // show command line which will launch via execv
//fprintf(stdout, "INFO  (%s): execv command.\n", argv[0]);
//    fprintf(stdout, "      (user=%s) \%> %s", suser, sur_dispatch_exe);
    fprintf(stdout, "INFO  (%s): Executing as user=%s \%> %s ", argv[0], suser, sur_dispatch_exe);
    
    // loop thru each file passed on the command line
    for(ix=3; argv[ix]; ix++) {
	fprintf(stdout, " %s", argv[ix]);
    }
    fprintf(stdout, "\n");


    // Like all of the exec functions, execv replaces the calling process image with a new process image. 
    // This has the effect of running a new progam with the process ID of the calling process. 
    // Note that a new process is not started; the new process image simply overlays the original process image. 
    // The execv function is most commonly used to overlay a process image that has been created by a call to the fork function.
    //
    // NOTE: &argv[2] contains all the cmd line args AFTER the 2 element.  aka: argv[3], argv[4], ...argv[n]
    //       Example: execv( sur_dispatch, <cmd line to execute with new UID> )
    if (execv (sur_dispatch_exe, &argv[2]) == -1) {
	fprintf(stderr, "ERROR (%s): execv command failed.\n", argv[0]);

	fprintf(stderr, "ERROR (%s): System call command failed.   \%> %s ", argv[0], sur_dispatch_exe);
	// loop thru each file passed on the command line
	for(ix=3; argv[ix]; ix++) {
	    fprintf(stdout, " %s", argv[ix]);
	}
	fprintf(stdout, "\n");
	fprintf(stdout, "Exiting...\n");

	// exit on error
	exit (1);
    } else {
	fprintf(stdout, "INFO  (%s): sur_dispatch_exe completed successfully.\n", argv[0], sur_dispatch_exe);
    }

    exit(1);

} 


/*
Name
    setuid - set user identity

Synopsis
    #include <sys/types.h>
    #include <unistd.h>
    int setuid(uid_t uid);

Description
    setuid() sets the effective user ID of the calling process. If the effective 
    UID of the caller is root, the real UID and saved set-user-ID are also set.
    Under Linux, setuid() is implemented like the POSIX version with the _POSIX_SAVED_IDS 
    feature. This allows a set-user-ID (other than root) program to drop all of its user 
    privileges, do some un-privileged work, and then reengage the original effective 
    user ID in a secure manner.

    If the user is root or the program is set-user-ID-root, special care must be taken. 
    The setuid() function checks the effective user ID of the caller and if it is the 
    superuser, all process-related user ID's are set to uid. After this has occurred, 
    it is impossible for the program to regain root privileges.

    Thus, a set-user-ID-root program wishing to temporarily drop root privileges, assume 
    the identity of an unprivileged user, and then regain root privileges afterward cannot 
    use setuid(). You can accomplish this with seteuid(2).

Return Value
    On success, zero is returned. On error, -1 is returned, and errno is set appropriately.

*/
# Change User Description Committed
#4 19638 netapp delete added files since agnes original
#3 19478 netapp Additons:

1.    Added in snapshot deletion capability
2.    Created separate user clone mount directory, which can be different from the base directory
3.    Cleaned up error handling for all p4 flex calls, so errors are handled with understandable output, versus program crashes
4.    Added in ability to specify volume owner when creating a volume with �p4 flex volume �s �u�.
#2 19476 netapp added new files to address these changes:
1.    Added in snapshot deletion capability
2.    Created separate user clone mount directory, which can be different from the base directory
3.    Cleaned up error handling for all p4 flex calls, so errors are handled with understandable output, versus program crashes
4.    Added in ability to specify volume owner when creating a volume with �p4 flex volume �s �u�.
#1 19474 netapp Uploaded new files for project.
Enhancements include:
1.    Added in snapshot deletion capability
2.    Created separate user clone mount directory, which can be different from the base directory
3.    Cleaned up error handling for all p4 flex calls, so errors are handled with understandable output, versus program crashes
4.    Added in ability to specify volume owner when creating a volume with �p4 flex volume �s �u�.