(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.4.1     }
262                            while (0);
263 kumpf          1.4     
264 kumpf          1.5     #if !defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
265 venkat.puvvada 1.5.4.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.4.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