(file) Return to PAMAuth.h CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Executor

  1 kumpf 1.2 /*
  2           //%2006////////////////////////////////////////////////////////////////////////
  3           //
  4           // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
  5           // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
  6           // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
  7           // IBM Corp.; EMC Corporation, The Open Group.
  8           // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
  9           // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
 10           // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 11           // EMC Corporation; VERITAS Software Corporation; The Open Group.
 12           // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 13           // EMC Corporation; Symantec Corporation; The Open Group.
 14           //
 15           // Permission is hereby granted, free of charge, to any person obtaining a copy
 16           // of this software and associated documentation files (the "Software"), to
 17           // deal in the Software without restriction, including without limitation the
 18           // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 19           // sell copies of the Software, and to permit persons to whom the Software is
 20           // furnished to do so, subject to the following conditions:
 21           // 
 22 kumpf 1.2 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 23           // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 24           // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 25           // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 26           // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 27           // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 28           // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 29           // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 30           //
 31           //==============================================================================
 32           //
 33           //%/////////////////////////////////////////////////////////////////////////////
 34           */
 35           
 36           #ifndef Executor_PAMAuth_h
 37           #define Executor_PAMAuth_h
 38           
 39           #if !defined(PEGASUS_PAM_AUTHENTICATION)
 40           # error "Do not include this file without defining PEGASUS_PAM_AUTHENTICATION"
 41           #endif
 42           
 43 kumpf 1.2 #include <sys/types.h>
 44           #include <sys/socket.h>
 45           #include <sys/wait.h>
 46           #include <unistd.h>
 47           #include <stdio.h>
 48           #include <errno.h>
 49           #include <string.h>
 50           #include <Executor/Strlcpy.h>
 51           #include <Executor/Strlcat.h>
 52           #include <security/pam_appl.h>
 53 kumpf 1.4 #include <Executor/Defines.h>
 54           #include <Executor/Socket.h>
 55 kumpf 1.2 
 56           /*
 57           **==============================================================================
 58           **
 59           **     This program is used to authenticate users with the "Basic PAM
 60           **     Authentication" scheme. It was originally written to isolate memory
 61           **     PAM module errors to an external process.
 62           **
 63           **     This header defines two functions that may be called by clients of this
 64           **     process (the parent process).
 65           **
 66           **         CimserveraAuthenticate()
 67           **         CimserveraValidateUser()
 68           **
 69           **     Each functions forks and executes a child process that carries out
 70           **     the request and then exits immediately. The parent and child proceses
 71           **     communicate over a local domain socket, created by the parent just
 72           **     before executing the client program.
 73           **
 74           **     Both of the functions above are defined in the header to avoid the need
 75           **     to link a separate client library.
 76 kumpf 1.2 **
 77           **     CAUTION: This program must not depend on any Pegasus libraries since
 78           **     it is used by the executor process.
 79           **
 80           **==============================================================================
 81           */
 82           
 83           /*
 84           **==============================================================================
 85           **
 86           ** CimserveraStart()
 87           **
 88           **     Starts the CIMSERVERA program, returning a socket used to communicate
 89           **     with it.
 90           **
 91           **==============================================================================
 92           */
 93           
 94           static int CimserveraStart(int* sock)
 95           {
 96               int pair[2];
 97 kumpf 1.2     int pid;
 98           
 99               /* Get absolute path of CIMSERVERA program. */
100           
101               char path[EXECUTOR_BUFFER_SIZE];
102           
103               if (PEGASUS_PAM_STANDALONE_PROC_NAME[0] == '/')
104                   Strlcpy(path, PEGASUS_PAM_STANDALONE_PROC_NAME, EXECUTOR_BUFFER_SIZE);
105               else
106               {
107                   /* Flawfinder: ignore */
108                   const char* home = getenv("PEGASUS_HOME");
109           
110                   if (!home)
111                       return -1;
112           
113                   Strlcpy(path, home, EXECUTOR_BUFFER_SIZE);
114                   Strlcat(path, "/", EXECUTOR_BUFFER_SIZE);
115                   Strlcat(path, PEGASUS_PAM_STANDALONE_PROC_NAME, EXECUTOR_BUFFER_SIZE);
116               }
117           
118 kumpf 1.2     /* Create socket pair for communicating with child process. */
119           
120               if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) != 0)
121                   return -1;
122           
123               /* Fork child: */
124           
125               pid = fork();
126           
127               if (pid < 0)
128 kumpf 1.3     {
129                   close(pair[0]);
130                   close(pair[1]);
131 kumpf 1.2         return -1;
132 kumpf 1.3     }
133 kumpf 1.2 
134               /* Child process: */
135           
136               if (pid == 0)
137               {
138                   char sockStr[32];
139                   const char* argv[3];
140           
141                   close(pair[1]);
142           
143                   /* Convert socket number to string. */
144           
145                   sprintf(sockStr, "%d", pair[0]);
146           
147                   /* Build arguments for execv(). */
148           
149                   argv[0] = CIMSERVERA;
150                   argv[1] = sockStr;
151                   argv[2] = 0;
152           
153                   /* Execute child: */
154 kumpf 1.2 
155                   /* Flawfinder: ignore */
156                   execv(path, (char**)argv);
157                   close(pair[0]);
158                   _exit(0);
159               }
160           
161               /* Parent process: */
162           
163               close(pair[0]);
164           
165               *sock = pair[1];
166               return pid;
167           }
168           
169           /*
170           **==============================================================================
171           **
172           ** CimserveraRequest
173           **
174           **==============================================================================
175 kumpf 1.2 */
176           
177           typedef struct CimserveraRequestStruct
178           {
179               char arg0[EXECUTOR_BUFFER_SIZE];
180               char arg1[EXECUTOR_BUFFER_SIZE];
181               char arg2[EXECUTOR_BUFFER_SIZE];
182           }
183           CimserveraRequest;
184           
185           /*
186           **==============================================================================
187           **
188 kumpf 1.4 ** CimserveraResponse
189           **
190           **==============================================================================
191           */
192           
193           typedef struct CimserveraResponseStruct
194           {
195               /* '0' means authentication successful. '-1' means authentication failed. */
196               int status;
197           }
198           CimserveraResponse;
199           
200           /*
201           **==============================================================================
202           **
203 kumpf 1.2 ** CimserveraAuthenticate()
204           **
205           **==============================================================================
206           */
207           
208           static int CimserveraAuthenticate(const char* username, const char* password)
209           {
210               int sock;
211               int pid;
212               int status;
213           
214               /* Create the CIMSERVERA process. */
215           
216               pid = CimserveraStart(&sock);
217           
218               if (pid == -1)
219                   return -1;
220           
221               /* Send request, get response. */
222           
223               status = 0;
224 kumpf 1.2 
225               do
226               {
227                   CimserveraRequest request;
228 kumpf 1.4         CimserveraResponse response;
229 kumpf 1.2         int childStatus;
230           
231                   /* Send request to CIMSERVERA process. */
232           
233                   memset(&request, 0, sizeof(request));
234                   Strlcpy(request.arg0, "authenticate", EXECUTOR_BUFFER_SIZE);
235                   Strlcpy(request.arg1, username, EXECUTOR_BUFFER_SIZE);
236                   Strlcpy(request.arg2, password, EXECUTOR_BUFFER_SIZE);
237           
238 kumpf 1.4         if (SendBlock(sock, &request, sizeof(request)) != sizeof(request))
239 kumpf 1.2         {
240                       status = -1;
241                       break;
242                   }
243           
244 kumpf 1.4         /* Receive response from CIMSERVERA process. */
245           
246                   if (RecvBlock(sock, &response, sizeof(response)) != sizeof(response))
247                   {
248                       status = -1;
249                       break;
250                   }
251 kumpf 1.2 
252 kumpf 1.4         /* Check status. */
253 kumpf 1.2 
254 kumpf 1.4         if (response.status != 0)
255 kumpf 1.2         {
256                       status = -1;
257                       break;
258                   }
259 kumpf 1.4 
260                   /* Get exit status from CIMSERVERA program. */
261           
262                   waitpid(pid, &childStatus, 0);
263 kumpf 1.2     }
264               while (0);
265           
266               close(sock);
267           
268               return status;
269           }
270           
271           /*
272           **==============================================================================
273           **
274           ** CimserveraValidateUser()
275           **
276           **==============================================================================
277           */
278           
279           static int CimserveraValidateUser(const char* username)
280           {
281               int sock;
282               int pid;
283               int status;
284 kumpf 1.2 
285               /* Create the CIMSERVERA process. */
286           
287               pid = CimserveraStart(&sock);
288           
289               if (pid == -1)
290                   return -1;
291           
292               /* Send request, get response. */
293           
294               status = 0;
295           
296               do
297               {
298                   CimserveraRequest request;
299 kumpf 1.4         CimserveraResponse response;
300 kumpf 1.2         int childStatus;
301           
302                   /* Send request to CIMSERVERA process. */
303           
304                   memset(&request, 0, sizeof(request));
305                   Strlcpy(request.arg0, "validateUser", EXECUTOR_BUFFER_SIZE);
306                   Strlcpy(request.arg1, username, EXECUTOR_BUFFER_SIZE);
307           
308 kumpf 1.4         if (SendBlock(sock, &request, sizeof(request)) != sizeof(request))
309 kumpf 1.2         {
310                       status = -1;
311                       break;
312                   }
313           
314 kumpf 1.4         /* Receive response from CIMSERVERA process. */
315           
316                   if (RecvBlock(sock, &response, sizeof(response)) != sizeof(response))
317                   {
318                       status = -1;
319                       break;
320                   }
321 kumpf 1.2 
322 kumpf 1.4         /* Check status. */
323 kumpf 1.2 
324 kumpf 1.4         if (response.status != 0)
325 kumpf 1.2         {
326                       status = -1;
327                       break;
328                   }
329 kumpf 1.4 
330                   /* Get exit status from CIMSERVERA program. */
331           
332                   waitpid(pid, &childStatus, 0);
333 kumpf 1.2     }
334               while (0);
335           
336               close(sock);
337           
338               return status;
339           }
340           
341           /*
342           **==============================================================================
343           **
344           ** struct PAMData
345           **
346           **     Client data passed to PAM routines.
347           **
348           **==============================================================================
349           */
350           
351           typedef struct PAMDataStruct
352           {
353               const char* password;
354 kumpf 1.2 }
355           PAMData;
356           
357           /*
358           **==============================================================================
359           **
360           ** PAMAuthenticateCallback()
361           **
362           **     Callback used by PAMAuthenticate().
363           **
364           **==============================================================================
365           */
366           
367           static int PAMAuthenticateCallback(
368               int num_msg,
369           #if defined(PEGASUS_OS_LINUX)
370               const struct pam_message** msg,
371           #else
372               struct pam_message** msg,
373           #endif
374               struct pam_response** resp,
375 kumpf 1.2     void* appdata_ptr)
376           {
377               PAMData* data = (PAMData*)appdata_ptr;
378               int i;
379           
380               if (num_msg > 0)
381               {
382                   *resp = (struct pam_response*)calloc(
383                       num_msg, sizeof(struct pam_response));
384           
385                   if (*resp == NULL)
386                       return PAM_BUF_ERR;
387               }
388               else
389                   return PAM_CONV_ERR;
390           
391               for (i = 0; i < num_msg; i++)
392               {
393                   switch (msg[i]->msg_style)
394                   {
395                       case PAM_PROMPT_ECHO_OFF:
396 kumpf 1.2             {
397                           resp[i]->resp = (char*)malloc(PAM_MAX_MSG_SIZE);
398                           Strlcpy(resp[i]->resp, data->password, PAM_MAX_MSG_SIZE);
399                           resp[i]->resp_retcode = 0;
400                           break;
401                       }
402           
403                       default:
404                           return PAM_CONV_ERR;
405                   }
406               }
407           
408               return PAM_SUCCESS;
409           }
410           
411           /*
412           **==============================================================================
413           **
414           ** PAMValidateUserCallback()
415           **
416           **     Callback used by PAMValidateUser().
417 kumpf 1.2 **
418           **==============================================================================
419           */
420           
421           static int PAMValidateUserCallback(
422               int num_msg,
423           #if defined(PEGASUS_OS_LINUX)
424               const struct pam_message** msg,
425           #else
426               struct pam_message** msg,
427           #endif
428               struct pam_response** resp,
429               void* appdata_ptr)
430           {
431               /* Unused */
432               msg = 0;
433           
434               /* Unused */
435               appdata_ptr = 0;
436           
437               if (num_msg > 0)
438 kumpf 1.2     {
439                   *resp = (struct pam_response*)calloc(
440                       num_msg, sizeof(struct pam_response));
441           
442                   if (*resp == NULL)
443                       return PAM_BUF_ERR;
444               }
445               else
446                   return PAM_CONV_ERR;
447           
448               return PAM_SUCCESS;
449           }
450           
451           /*
452           **==============================================================================
453           **
454           ** PAMAuthenticateInProcess()
455           **
456           **     Performs basic PAM authentication on the given username and password.
457           **
458           **==============================================================================
459 kumpf 1.2 */
460           
461           static int PAMAuthenticateInProcess(
462               const char* username, const char* password)
463           {
464               PAMData data;
465               struct pam_conv pconv;
466               pam_handle_t* handle;
467           
468               data.password = password;
469               pconv.conv = PAMAuthenticateCallback;
470               pconv.appdata_ptr = &data;
471           
472           
473               if (pam_start("wbem", username, &pconv, &handle) != PAM_SUCCESS)
474                   return -1;
475           
476               if (pam_authenticate(handle, 0) != PAM_SUCCESS)
477               {
478                   pam_end(handle, 0);
479                   return -1;
480 kumpf 1.2     }
481           
482               if (pam_acct_mgmt(handle, 0) != PAM_SUCCESS)
483               {
484                   pam_end(handle, 0);
485                   return -1;
486               }
487           
488               pam_end(handle, 0);
489           
490               return 0;
491           }
492           
493           /*
494           **==============================================================================
495           **
496           ** PAMValidateUserInProcess()
497           **
498           **     Validate that the *username* refers to a valid PAM user.
499           **
500           **==============================================================================
501 kumpf 1.2 */
502           
503           static int PAMValidateUserInProcess(const char* username)
504           {
505               PAMData data;
506               struct pam_conv pconv;
507               pam_handle_t* phandle;
508           
509               pconv.conv = PAMValidateUserCallback;
510               pconv.appdata_ptr = &data;
511           
512               if (pam_start("wbem", username, &pconv, &phandle) != PAM_SUCCESS)
513                   return -1;
514           
515               if (pam_acct_mgmt(phandle, 0) != PAM_SUCCESS)
516               {
517                   pam_end(phandle, 0);
518                   return -1;
519               }
520           
521               pam_end(phandle, 0);
522 kumpf 1.2 
523               return 0;
524           }
525           
526           /*
527           **==============================================================================
528           **
529           ** PAMAuthenticate()
530           **
531           **     Performs basic PAM authentication on the given username and password.
532           **
533           **==============================================================================
534           */
535           
536           static int PAMAuthenticate(const char* username, const char* password)
537           {
538           #ifdef PEGASUS_USE_PAM_STANDALONE_PROC
539               return CimserveraAuthenticate(username, password);
540           #else
541               return PAMAuthenticateInProcess(username, password);
542           #endif
543 kumpf 1.2 }
544           
545           /*
546           **==============================================================================
547           **
548           ** PAMValidateUser()
549           **
550           **     Validate that the *username* refers to a valid PAM user.
551           **
552           **==============================================================================
553           */
554           
555           static int PAMValidateUser(const char* username)
556           {
557           #ifdef PEGASUS_USE_PAM_STANDALONE_PROC
558               return CimserveraValidateUser(username);
559           #else
560               return PAMValidateUserInProcess(username);
561           #endif
562           }
563           
564 kumpf 1.2 #endif /* Executor_PAMAuth_h */

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2