1 /* Written by Ricky Zhou <ricky@fedoraproject.org>
2 * Fredrik Thulin <fredrik@yubico.com> implemented pam_modutil_drop_priv
3 *
4 * Copyright (c) 2011-2014 Yubico AB
5 * Copyright (c) 2011 Ricky Zhou <ricky@fedoraproject.org>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * * Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials provided
18 * with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #ifndef HAVE_PAM_MODUTIL_DROP_PRIV
34
35 #include <unistd.h>
36 #include <pwd.h>
37 #include <grp.h>
38 #include <errno.h>
39 #include <string.h>
40 #include <stdlib.h>
41
42 #include "drop_privs.h"
43 #include "util.h"
44
45 #ifdef HAVE_SECURITY_PAM_APPL_H
46 #include <security/pam_appl.h>
47 #endif
48 #ifdef HAVE_SECURITY_PAM_MODULES_H
49 #include <security/pam_modules.h>
50 #endif
51
52
pam_modutil_drop_priv(pam_handle_t * pamh,struct _ykpam_privs * privs,struct passwd * pw)53 int pam_modutil_drop_priv(pam_handle_t *pamh, struct _ykpam_privs *privs, struct passwd *pw) {
54 privs->saved_euid = geteuid();
55 privs->saved_egid = getegid();
56
57 if ((privs->saved_euid == pw->pw_uid) && (privs->saved_egid == pw->pw_gid)) {
58 D (privs->debug_file, "Privilges already dropped, pretend it is all right");
59 return 0;
60 }
61
62 privs->saved_groups_length = getgroups(0, NULL);
63 if (privs->saved_groups_length < 0) {
64 D (privs->debug_file, "getgroups: %s", strerror(errno));
65 return -1;
66 }
67
68 if (privs->saved_groups_length > SAVED_GROUPS_MAX_LEN) {
69 D (privs->debug_file, "to many groups, limiting.");
70 privs->saved_groups_length = SAVED_GROUPS_MAX_LEN;
71 }
72
73 if (privs->saved_groups_length > 0) {
74 if (getgroups(privs->saved_groups_length, privs->saved_groups) < 0) {
75 D (privs->debug_file, "getgroups: %s", strerror(errno));
76 goto free_out;
77 }
78 }
79
80 if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
81 D (privs->debug_file, "initgroups: %s", strerror(errno));
82 goto free_out;
83 }
84
85 if (setegid(pw->pw_gid) < 0) {
86 D (privs->debug_file, "setegid: %s", strerror(errno));
87 goto free_out;
88 }
89
90 if (seteuid(pw->pw_uid) < 0) {
91 D (privs->debug_file, "seteuid: %s", strerror(errno));
92 goto free_out;
93 }
94
95 return 0;
96 free_out:
97 return -1;
98 }
99
pam_modutil_regain_priv(pam_handle_t * pamh,struct _ykpam_privs * privs)100 int pam_modutil_regain_priv(pam_handle_t *pamh, struct _ykpam_privs *privs) {
101 if ((privs->saved_euid == geteuid()) && (privs->saved_egid == getegid())) {
102 D (privs->debug_file, "Privilges already as requested, pretend it is all right");
103 return 0;
104 }
105
106 if (seteuid(privs->saved_euid) < 0) {
107 D (privs->debug_file, "seteuid: %s", strerror(errno));
108 return -1;
109 }
110
111 if (setegid(privs->saved_egid) < 0) {
112 D (privs->debug_file, "setegid: %s", strerror(errno));
113 return -1;
114 }
115
116 if (setgroups(privs->saved_groups_length, privs->saved_groups) < 0) {
117 D (privs->debug_file, "setgroups: %s", strerror(errno));
118 return -1;
119 }
120
121 return 0;
122 }
123
124 #endif // HAVE_PAM_MODUTIL_DROP_PRIV
125