(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 kumpf 1.5 **         PAMAuthenticate()
 67           **         PAMValidateUser()
 68 kumpf 1.2 **
 69 kumpf 1.5 **     Depending on the PEGASUS_USE_PAM_STANDALONE_PROC build flag, these
 70           **     functions either call PAM directly or fork and execute a child process
 71           **     that performs the requested PAM operation and then exits immediately.
 72           **     The parent and child proceses communicate over a local domain socket,
 73           **     created by the parent just before executing the client program.
 74 kumpf 1.2 **
 75 kumpf 1.5 **     These functions are defined in a header file to avoid the need
 76 kumpf 1.2 **     to link a separate client library.
 77           **
 78           **     CAUTION: This program must not depend on any Pegasus libraries since
 79           **     it is used by the executor process.
 80           **
 81           **==============================================================================
 82           */
 83           
 84           /*
 85           **==============================================================================
 86           **
 87           ** CimserveraStart()
 88           **
 89           **     Starts the CIMSERVERA program, returning a socket used to communicate
 90           **     with it.
 91           **
 92           **==============================================================================
 93           */
 94           
 95           static int CimserveraStart(int* sock)
 96           {
 97 kumpf 1.2     int pair[2];
 98               int pid;
 99           
100               /* Get absolute path of CIMSERVERA program. */
101           
102               char path[EXECUTOR_BUFFER_SIZE];
103           
104               if (PEGASUS_PAM_STANDALONE_PROC_NAME[0] == '/')
105                   Strlcpy(path, PEGASUS_PAM_STANDALONE_PROC_NAME, EXECUTOR_BUFFER_SIZE);
106               else
107               {
108                   /* Flawfinder: ignore */
109                   const char* home = getenv("PEGASUS_HOME");
110           
111                   if (!home)
112                       return -1;
113           
114                   Strlcpy(path, home, EXECUTOR_BUFFER_SIZE);
115                   Strlcat(path, "/", EXECUTOR_BUFFER_SIZE);
116                   Strlcat(path, PEGASUS_PAM_STANDALONE_PROC_NAME, EXECUTOR_BUFFER_SIZE);
117               }
118 kumpf 1.2 
119               /* Create socket pair for communicating with child process. */
120           
121               if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) != 0)
122                   return -1;
123           
124               /* Fork child: */
125           
126               pid = fork();
127           
128               if (pid < 0)
129 kumpf 1.3     {
130                   close(pair[0]);
131                   close(pair[1]);
132 kumpf 1.2         return -1;
133 kumpf 1.3     }
134 kumpf 1.2 
135               /* Child process: */
136           
137               if (pid == 0)
138               {
139                   char sockStr[32];
140                   const char* argv[3];
141           
142                   close(pair[1]);
143           
144                   /* Convert socket number to string. */
145           
146                   sprintf(sockStr, "%d", pair[0]);
147           
148                   /* Build arguments for execv(). */
149           
150                   argv[0] = CIMSERVERA;
151                   argv[1] = sockStr;
152                   argv[2] = 0;
153           
154                   /* Execute child: */
155 kumpf 1.2 
156                   /* Flawfinder: ignore */
157                   execv(path, (char**)argv);
158                   close(pair[0]);
159                   _exit(0);
160               }
161           
162               /* Parent process: */
163           
164               close(pair[0]);
165           
166               *sock = pair[1];
167               return pid;
168           }
169           
170           /*
171           **==============================================================================
172           **
173           ** CimserveraRequest
174           **
175           **==============================================================================
176 kumpf 1.2 */
177           
178           typedef struct CimserveraRequestStruct
179           {
180               char arg0[EXECUTOR_BUFFER_SIZE];
181               char arg1[EXECUTOR_BUFFER_SIZE];
182               char arg2[EXECUTOR_BUFFER_SIZE];
183           }
184           CimserveraRequest;
185           
186           /*
187           **==============================================================================
188           **
189 kumpf 1.4 ** CimserveraResponse
190           **
191           **==============================================================================
192           */
193           
194           typedef struct CimserveraResponseStruct
195           {
196               /* '0' means authentication successful. '-1' means authentication failed. */
197               int status;
198           }
199           CimserveraResponse;
200           
201           /*
202           **==============================================================================
203           **
204 kumpf 1.5 ** CimserveraProcessOperation()
205 kumpf 1.2 **
206           **==============================================================================
207           */
208           
209 kumpf 1.5 static int CimserveraProcessOperation(
210               const char* operationName,
211               const char* username,
212               const char* password)
213 kumpf 1.2 {
214               int sock;
215               int pid;
216               int status;
217           
218               /* Create the CIMSERVERA process. */
219           
220               pid = CimserveraStart(&sock);
221           
222               if (pid == -1)
223                   return -1;
224           
225               /* Send request, get response. */
226           
227               status = 0;
228           
229               do
230               {
231                   CimserveraRequest request;
232 kumpf 1.4         CimserveraResponse response;
233 kumpf 1.2 
234                   /* Send request to CIMSERVERA process. */
235           
236                   memset(&request, 0, sizeof(request));
237 kumpf 1.5         Strlcpy(request.arg0, operationName, EXECUTOR_BUFFER_SIZE);
238 kumpf 1.2         Strlcpy(request.arg1, username, EXECUTOR_BUFFER_SIZE);
239                   Strlcpy(request.arg2, password, EXECUTOR_BUFFER_SIZE);
240           
241 kumpf 1.4         if (SendBlock(sock, &request, sizeof(request)) != sizeof(request))
242 kumpf 1.2         {
243                       status = -1;
244                       break;
245                   }
246           
247 kumpf 1.4         /* Receive response from CIMSERVERA process. */
248           
249                   if (RecvBlock(sock, &response, sizeof(response)) != sizeof(response))
250                   {
251                       status = -1;
252                       break;
253                   }
254 kumpf 1.2 
255 kumpf 1.4         /* Check status. */
256 kumpf 1.2 
257 kumpf 1.4         if (response.status != 0)
258 kumpf 1.2         {
259                       status = -1;
260                   }
261 venkat.puvvada 1.5.20.1     }
262                             while (0);
263 kumpf          1.4      
264 kumpf          1.5      #if !defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
265 venkat.puvvada 1.5.20.1     /* When called from the main cimserver process, the cimservera
266                                exit status must be harvested explicitly to prevent zombies.
267                             */
268 kumpf          1.4      
269 venkat.puvvada 1.5.20.1     while ((waitpid(pid, 0, 0) == -1) && (errno == EINTR))
270                                 ;
271 kumpf          1.5      #endif
272 kumpf          1.2      
273                             close(sock);
274                         
275                             return status;
276                         }
277                         
278                         /*
279                         **==============================================================================
280                         **
281                         ** struct PAMData
282                         **
283                         **     Client data passed to PAM routines.
284                         **
285                         **==============================================================================
286                         */
287                         
288                         typedef struct PAMDataStruct
289                         {
290                             const char* password;
291                         }
292                         PAMData;
293 kumpf          1.2      
294                         /*
295                         **==============================================================================
296                         **
297                         ** PAMAuthenticateCallback()
298                         **
299                         **     Callback used by PAMAuthenticate().
300                         **
301                         **==============================================================================
302                         */
303                         
304                         static int PAMAuthenticateCallback(
305                             int num_msg,
306                         #if defined(PEGASUS_OS_LINUX)
307                             const struct pam_message** msg,
308                         #else
309                             struct pam_message** msg,
310                         #endif
311                             struct pam_response** resp,
312                             void* appdata_ptr)
313                         {
314 kumpf          1.2          PAMData* data = (PAMData*)appdata_ptr;
315                             int i;
316                         
317                             if (num_msg > 0)
318                             {
319                                 *resp = (struct pam_response*)calloc(
320                                     num_msg, sizeof(struct pam_response));
321                         
322                                 if (*resp == NULL)
323                                     return PAM_BUF_ERR;
324                             }
325                             else
326                                 return PAM_CONV_ERR;
327                         
328                             for (i = 0; i < num_msg; i++)
329                             {
330                                 switch (msg[i]->msg_style)
331                                 {
332                                     case PAM_PROMPT_ECHO_OFF:
333                                     {
334                                         resp[i]->resp = (char*)malloc(PAM_MAX_MSG_SIZE);
335 kumpf          1.2                      Strlcpy(resp[i]->resp, data->password, PAM_MAX_MSG_SIZE);
336                                         resp[i]->resp_retcode = 0;
337                                         break;
338                                     }
339                         
340                                     default:
341                                         return PAM_CONV_ERR;
342                                 }
343                             }
344                         
345                             return PAM_SUCCESS;
346                         }
347                         
348                         /*
349                         **==============================================================================
350                         **
351                         ** PAMValidateUserCallback()
352                         **
353                         **     Callback used by PAMValidateUser().
354                         **
355                         **==============================================================================
356 kumpf          1.2      */
357                         
358                         static int PAMValidateUserCallback(
359                             int num_msg,
360                         #if defined(PEGASUS_OS_LINUX)
361                             const struct pam_message** msg,
362                         #else
363                             struct pam_message** msg,
364                         #endif
365                             struct pam_response** resp,
366                             void* appdata_ptr)
367                         {
368                             /* Unused */
369                             msg = 0;
370                         
371                             /* Unused */
372                             appdata_ptr = 0;
373                         
374                             if (num_msg > 0)
375                             {
376                                 *resp = (struct pam_response*)calloc(
377 kumpf          1.2                  num_msg, sizeof(struct pam_response));
378                         
379                                 if (*resp == NULL)
380                                     return PAM_BUF_ERR;
381                             }
382                             else
383                                 return PAM_CONV_ERR;
384                         
385                             return PAM_SUCCESS;
386                         }
387                         
388                         /*
389                         **==============================================================================
390                         **
391                         ** PAMAuthenticateInProcess()
392                         **
393                         **     Performs basic PAM authentication on the given username and password.
394                         **
395                         **==============================================================================
396                         */
397                         
398 kumpf          1.2      static int PAMAuthenticateInProcess(
399                             const char* username, const char* password)
400                         {
401                             PAMData data;
402                             struct pam_conv pconv;
403                             pam_handle_t* handle;
404                         
405                             data.password = password;
406                             pconv.conv = PAMAuthenticateCallback;
407                             pconv.appdata_ptr = &data;
408                         
409                         
410                             if (pam_start("wbem", username, &pconv, &handle) != PAM_SUCCESS)
411                                 return -1;
412                         
413                             if (pam_authenticate(handle, 0) != PAM_SUCCESS)
414                             {
415                                 pam_end(handle, 0);
416                                 return -1;
417                             }
418                         
419 kumpf          1.2          if (pam_acct_mgmt(handle, 0) != PAM_SUCCESS)
420                             {
421                                 pam_end(handle, 0);
422                                 return -1;
423                             }
424                         
425                             pam_end(handle, 0);
426                         
427                             return 0;
428                         }
429                         
430                         /*
431                         **==============================================================================
432                         **
433                         ** PAMValidateUserInProcess()
434                         **
435                         **     Validate that the *username* refers to a valid PAM user.
436                         **
437                         **==============================================================================
438                         */
439                         
440 kumpf          1.2      static int PAMValidateUserInProcess(const char* username)
441                         {
442                             PAMData data;
443                             struct pam_conv pconv;
444                             pam_handle_t* phandle;
445                         
446                             pconv.conv = PAMValidateUserCallback;
447                             pconv.appdata_ptr = &data;
448                         
449                             if (pam_start("wbem", username, &pconv, &phandle) != PAM_SUCCESS)
450                                 return -1;
451                         
452                             if (pam_acct_mgmt(phandle, 0) != PAM_SUCCESS)
453                             {
454                                 pam_end(phandle, 0);
455                                 return -1;
456                             }
457                         
458                             pam_end(phandle, 0);
459                         
460                             return 0;
461 kumpf          1.2      }
462                         
463                         /*
464                         **==============================================================================
465                         **
466                         ** PAMAuthenticate()
467                         **
468                         **     Performs basic PAM authentication on the given username and password.
469                         **
470                         **==============================================================================
471                         */
472                         
473                         static int PAMAuthenticate(const char* username, const char* password)
474                         {
475                         #ifdef PEGASUS_USE_PAM_STANDALONE_PROC
476 kumpf          1.5          return CimserveraProcessOperation("authenticate", username, password);
477 kumpf          1.2      #else
478                             return PAMAuthenticateInProcess(username, password);
479                         #endif
480                         }
481                         
482                         /*
483                         **==============================================================================
484                         **
485                         ** PAMValidateUser()
486                         **
487                         **     Validate that the *username* refers to a valid PAM user.
488                         **
489                         **==============================================================================
490                         */
491                         
492                         static int PAMValidateUser(const char* username)
493                         {
494                         #ifdef PEGASUS_USE_PAM_STANDALONE_PROC
495 kumpf          1.5          return CimserveraProcessOperation("validateUser", username, "");
496 kumpf          1.2      #else
497                             return PAMValidateUserInProcess(username);
498                         #endif
499                         }
500                         
501                         #endif /* Executor_PAMAuth_h */

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2