root/source3/client/get_printing_ticket.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. printargs
  2. main

   1 /*
   2    Copyright (C) Dan Winship                    2006
   3    Copyright (C) Jeremy Allison                 2006
   4 
   5    This program is free software; you can redistribute it and/or modify
   6    it under the terms of the GNU General Public License as published by
   7    the Free Software Foundation; either version 2 of the License, or
   8    (at your option) any later version.
   9 
  10    This program is distributed in the hope that it will be useful,
  11    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13    GNU General Public License for more details.
  14 
  15    You should have received a copy of the GNU General Public License
  16    along with this program; if not, write to the Free Software
  17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18 */
  19 
  20 #define _GNU_SOURCE
  21 
  22 #include <stdio.h>
  23 #include <sys/types.h>
  24 #include <unistd.h>
  25 #include <pwd.h>
  26 #include <grp.h>
  27 #include <errno.h>
  28 
  29 #ifndef DEBUG_ERROR
  30 #define DEBUG_ERROR printf
  31 #endif
  32 
  33 /* Usage:
  34  *
  35  *   get_printing_ticket <smbspool cups args.>
  36  *
  37  * The cups args look like :
  38  *
  39  * [DEVICE_URI] job-id user title copies options [file]
  40  
  41  * Sets its uid to the given username and then invokes smbspool.
  42  */
  43 
  44 #if 0
  45 /* NEVER ENABLE THIS IT IS A SECURITY HOLE. USE ONLY FOR DEBUGGING. JRA. */
  46 int printargs(const char *name, int argc, char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
  47 {
  48         FILE *fp;
  49         int i;
  50         fp = fopen(name, "w");
  51         for ( i = 0; i < argc; i++) {
  52                 fprintf(fp, "argv[%d] = '%s'\n", i, argv[i]);
  53         }
  54         fclose(fp);
  55 }
  56 #endif
  57 
  58 char *null_envp[] = { NULL };
  59 
  60 int main (int argc, char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
  61 {
  62         uid_t uid, LP_UID;
  63         gid_t gid, LP_GID;
  64         struct passwd *pw;
  65 
  66         /* Get uid and gid of user lp */
  67         pw = getpwnam( "lp");
  68         if (!pw) {
  69                 DEBUG_ERROR ( "Unknown username lp\n");
  70                 return 1;
  71         }
  72         LP_UID = pw->pw_uid;
  73         if (LP_UID == (uid_t)-1) {
  74                 DEBUG_ERROR ("Bad uid %lu for user lp\n", (unsigned long)LP_UID);
  75                 return 1;
  76         }
  77         LP_GID = pw->pw_gid;
  78         if (LP_GID == (gid_t)-1) {
  79                 DEBUG_ERROR ("Bad gid %lu for user lp\n", (unsigned long)LP_GID);
  80                 return 1;
  81         }
  82 
  83         /* Check that calling uid/gid is "lp" or 0. (This hack doesn't have to
  84          * survive beyond CODE10, so we can safely hardcode the ids.)
  85          */
  86 
  87         /*
  88          * THE FOLLOWING IS DONE AS ROOT. BEWARE !!!!!!!
  89          */
  90 
  91         if (getuid() != LP_UID && getuid() != 0) {
  92                 DEBUG_ERROR ("Bad invoking uid %lu\n", (unsigned long)getuid ());
  93                 return 1;
  94         }
  95         if (getgid() != LP_GID && getgid() != 0) {
  96                 DEBUG_ERROR ("Bad invoking gid %lu\n", (unsigned long)getgid ());
  97                 return 1;
  98         }
  99 
 100         if (argc == 1) {
 101                 uid = LP_UID; /* Invoke as uid lp to do a query-only. */
 102         } else if (argc == 6 || argc == 7) {
 103                 pw = getpwnam(argv[2]);
 104                 if (!pw) {
 105                         DEBUG_ERROR ("Unknown username %s\n", argv[3]);
 106                         return 1;
 107                 }
 108                 uid = pw->pw_uid;
 109                 if (uid == (uid_t)-1) {
 110                         DEBUG_ERROR ("Bad uid %lu\n", (unsigned long)uid);
 111                         return 1;
 112                 }
 113                 gid = pw->pw_gid;
 114                 if (gid == (gid_t)-1) {
 115                         DEBUG_ERROR ("Bad gid %lu\n", (unsigned long)gid);
 116                         return 1;
 117                 }
 118         } else {
 119                 DEBUG_ERROR ("Bad number of args %u\n", (unsigned int)argc);
 120                 return 1;
 121         }
 122 
 123         if (uid != LP_UID && uid < 500) {
 124                 DEBUG_ERROR ("Bad uid %lu\n", (unsigned long)uid);
 125                 return 1;
 126         }
 127         if (setgroups (0, NULL) != 0) {
 128                 DEBUG_ERROR ("Couldn't clear groups: %s\n", strerror (errno));
 129                 return 1;
 130         }
 131         if (setresgid (gid, gid, gid) != 0) {
 132                 DEBUG_ERROR ("Couldn't set gid: %s\n", strerror (errno));
 133                 return 1;
 134         }
 135         if (setresuid (uid, uid, uid) != 0) {
 136                 DEBUG_ERROR ("Couldn't set uid: %s\n", strerror (errno));
 137                 return 1;
 138         }
 139 
 140         /* Clear the environment to ensure nothing can
 141            be loaded via LD_PRELOAD. Thanks to Sebastian Krahmer 
 142            from the SuSE security Team for reviewing this. */
 143         clearenv();
 144 
 145         /*
 146          * We are now the requested user.
 147          * From cups arg[0] is the smb:// uri and smbspool expects this
 148          */
 149 
 150         return execve ("/usr/bin/smbspool", argv, null_envp);
 151 }

/* [<][>][^][v][top][bottom][index][help] */