xref: /freebsd/contrib/pam-krb5/tests/fakepam/general.c (revision bf6873c5786e333d679a7838d28812febf479a8a)
1 /*
2  * Interface for fake PAM library, used for testing.
3  *
4  * This contains the basic public interfaces for the fake PAM library, used
5  * for testing, and some general utility functions.
6  *
7  * The canonical version of this file is maintained in the rra-c-util package,
8  * which can be found at <https://www.eyrie.org/~eagle/software/rra-c-util/>.
9  *
10  * Written by Russ Allbery <eagle@eyrie.org>
11  * Copyright 2010-2011, 2014
12  *     The Board of Trustees of the Leland Stanford Junior University
13  *
14  * Permission is hereby granted, free of charge, to any person obtaining a
15  * copy of this software and associated documentation files (the "Software"),
16  * to deal in the Software without restriction, including without limitation
17  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18  * and/or sell copies of the Software, and to permit persons to whom the
19  * Software is furnished to do so, subject to the following conditions:
20  *
21  * The above copyright notice and this permission notice shall be included in
22  * all copies or substantial portions of the Software.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
27  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30  * DEALINGS IN THE SOFTWARE.
31  *
32  * SPDX-License-Identifier: MIT
33  */
34 
35 #include <config.h>
36 #include <portable/pam.h>
37 #include <portable/system.h>
38 
39 #include <errno.h>
40 #include <pwd.h>
41 
42 #include <tests/fakepam/pam.h>
43 
44 /* Stores the static struct passwd returned by getpwnam if the name matches. */
45 static struct passwd *pwd_info = NULL;
46 
47 /* Used for unused parameters to silence gcc warnings. */
48 #define UNUSED __attribute__((__unused__))
49 
50 
51 /*
52  * Initializes the pam_handle_t data structure.  This function is only called
53  * from test programs, not from any of the module code.  We can put anything
54  * we want in this structure, since it's opaque to the regular code.
55  */
56 int
pam_start(const char * service_name,const char * user,const struct pam_conv * pam_conversation,pam_handle_t ** pamh)57 pam_start(const char *service_name, const char *user,
58           const struct pam_conv *pam_conversation, pam_handle_t **pamh)
59 {
60     struct pam_handle *handle;
61 
62     handle = calloc(1, sizeof(struct pam_handle));
63     if (handle == NULL)
64         return PAM_BUF_ERR;
65     handle->service = service_name;
66     handle->user = user;
67     handle->conversation = pam_conversation;
68     *pamh = handle;
69     return PAM_SUCCESS;
70 }
71 
72 
73 /*
74  * Free the pam_handle_t data structure and related resources.  This is
75  * important to test the data cleanups.  Freeing the memory is not strictly
76  * required since it's only used for testing, but it helps keep our memory
77  * usage clean so that we can run the test suite under valgrind.
78  */
79 int
pam_end(pam_handle_t * pamh,int status)80 pam_end(pam_handle_t *pamh, int status)
81 {
82     struct fakepam_data *item, *next;
83     size_t i;
84 
85     if (pamh->environ != NULL) {
86         for (i = 0; pamh->environ[i] != NULL; i++)
87             free(pamh->environ[i]);
88         free(pamh->environ);
89     }
90     free(pamh->authtok);
91     free(pamh->oldauthtok);
92     free(pamh->rhost);
93     free(pamh->ruser);
94     free(pamh->tty);
95     for (item = pamh->data; item != NULL;) {
96         if (item->cleanup != NULL)
97             item->cleanup(pamh, item->data, status);
98         free(item->name);
99         next = item->next;
100         free(item);
101         item = next;
102     }
103     free(pamh);
104     return PAM_SUCCESS;
105 }
106 
107 
108 /*
109  * Interface specific to this fake PAM library to set the struct passwd that's
110  * returned by getpwnam queries if the name matches.
111  */
112 void
pam_set_pwd(struct passwd * pwd)113 pam_set_pwd(struct passwd *pwd)
114 {
115     pwd_info = pwd;
116 }
117 
118 
119 /*
120  * For testing purposes, we want to be able to intercept getpwnam.  This is
121  * fairly easy on platforms that have pam_modutil_getpwnam, since then our
122  * code will always call that function and we can provide an implementation
123  * that does whatever we want.  For platforms that don't have that function,
124  * we'll try to intercept the C library getpwnam function.
125  *
126  * We store only one struct passwd data structure statically.  If the user
127  * we're looking up matches that, we return it; otherwise, we return NULL.
128  */
129 #ifdef HAVE_PAM_MODUTIL_GETPWNAM
130 struct passwd *
pam_modutil_getpwnam(pam_handle_t * pamh UNUSED,const char * name)131 pam_modutil_getpwnam(pam_handle_t *pamh UNUSED, const char *name)
132 {
133     if (pwd_info != NULL && strcmp(pwd_info->pw_name, name) == 0)
134         return pwd_info;
135     else {
136         errno = 0;
137         return NULL;
138     }
139 }
140 #else
141 struct passwd *
getpwnam(const char * name)142 getpwnam(const char *name)
143 {
144     if (pwd_info != NULL && strcmp(pwd_info->pw_name, name) == 0)
145         return pwd_info;
146     else {
147         errno = 0;
148         return NULL;
149     }
150 }
151 #endif
152