]>
Commit | Line | Data |
---|---|---|
8953caf3 DB |
1 | /* |
2 | * QEMU PAM authorization driver | |
3 | * | |
4 | * Copyright (c) 2018 Red Hat, Inc. | |
5 | * | |
6 | * This library is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU Lesser General Public | |
8 | * License as published by the Free Software Foundation; either | |
9 | * version 2 of the License, or (at your option) any later version. | |
10 | * | |
11 | * This library is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | * Lesser General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU Lesser General Public | |
17 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. | |
18 | * | |
19 | */ | |
20 | ||
21 | #include "qemu/osdep.h" | |
22 | #include "authz/pamacct.h" | |
23 | #include "authz/trace.h" | |
24 | #include "qom/object_interfaces.h" | |
25 | ||
26 | #include <security/pam_appl.h> | |
27 | ||
28 | ||
29 | static bool qauthz_pam_is_allowed(QAuthZ *authz, | |
30 | const char *identity, | |
31 | Error **errp) | |
32 | { | |
33 | QAuthZPAM *pauthz = QAUTHZ_PAM(authz); | |
34 | const struct pam_conv pam_conversation = { 0 }; | |
35 | pam_handle_t *pamh = NULL; | |
36 | int ret; | |
37 | ||
38 | trace_qauthz_pam_check(authz, identity, pauthz->service); | |
39 | ret = pam_start(pauthz->service, | |
40 | identity, | |
41 | &pam_conversation, | |
42 | &pamh); | |
43 | if (ret != PAM_SUCCESS) { | |
44 | error_setg(errp, "Unable to start PAM transaction: %s", | |
45 | pam_strerror(NULL, ret)); | |
46 | return false; | |
47 | } | |
48 | ||
49 | ret = pam_acct_mgmt(pamh, PAM_SILENT); | |
50 | pam_end(pamh, ret); | |
51 | if (ret != PAM_SUCCESS) { | |
52 | error_setg(errp, "Unable to authorize user '%s': %s", | |
53 | identity, pam_strerror(pamh, ret)); | |
54 | return false; | |
55 | } | |
56 | ||
57 | return true; | |
58 | } | |
59 | ||
60 | ||
61 | static void | |
62 | qauthz_pam_prop_set_service(Object *obj, | |
63 | const char *service, | |
64 | Error **errp G_GNUC_UNUSED) | |
65 | { | |
66 | QAuthZPAM *pauthz = QAUTHZ_PAM(obj); | |
67 | ||
68 | g_free(pauthz->service); | |
69 | pauthz->service = g_strdup(service); | |
70 | } | |
71 | ||
72 | ||
73 | static char * | |
74 | qauthz_pam_prop_get_service(Object *obj, | |
75 | Error **errp G_GNUC_UNUSED) | |
76 | { | |
77 | QAuthZPAM *pauthz = QAUTHZ_PAM(obj); | |
78 | ||
79 | return g_strdup(pauthz->service); | |
80 | } | |
81 | ||
82 | ||
83 | static void | |
84 | qauthz_pam_complete(UserCreatable *uc, Error **errp) | |
85 | { | |
86 | } | |
87 | ||
88 | ||
89 | static void | |
90 | qauthz_pam_finalize(Object *obj) | |
91 | { | |
92 | QAuthZPAM *pauthz = QAUTHZ_PAM(obj); | |
93 | ||
94 | g_free(pauthz->service); | |
95 | } | |
96 | ||
97 | ||
98 | static void | |
99 | qauthz_pam_class_init(ObjectClass *oc, void *data) | |
100 | { | |
101 | UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); | |
102 | QAuthZClass *authz = QAUTHZ_CLASS(oc); | |
103 | ||
104 | ucc->complete = qauthz_pam_complete; | |
105 | authz->is_allowed = qauthz_pam_is_allowed; | |
106 | ||
107 | object_class_property_add_str(oc, "service", | |
108 | qauthz_pam_prop_get_service, | |
109 | qauthz_pam_prop_set_service, | |
110 | NULL); | |
111 | } | |
112 | ||
113 | ||
114 | QAuthZPAM *qauthz_pam_new(const char *id, | |
115 | const char *service, | |
116 | Error **errp) | |
117 | { | |
118 | return QAUTHZ_PAM( | |
119 | object_new_with_props(TYPE_QAUTHZ_PAM, | |
120 | object_get_objects_root(), | |
121 | id, errp, | |
122 | "service", service, | |
123 | NULL)); | |
124 | } | |
125 | ||
126 | ||
127 | static const TypeInfo qauthz_pam_info = { | |
128 | .parent = TYPE_QAUTHZ, | |
129 | .name = TYPE_QAUTHZ_PAM, | |
130 | .instance_size = sizeof(QAuthZPAM), | |
131 | .instance_finalize = qauthz_pam_finalize, | |
132 | .class_size = sizeof(QAuthZPAMClass), | |
133 | .class_init = qauthz_pam_class_init, | |
134 | .interfaces = (InterfaceInfo[]) { | |
135 | { TYPE_USER_CREATABLE }, | |
136 | { } | |
137 | } | |
138 | }; | |
139 | ||
140 | ||
141 | static void | |
142 | qauthz_pam_register_types(void) | |
143 | { | |
144 | type_register_static(&qauthz_pam_info); | |
145 | } | |
146 | ||
147 | ||
148 | type_init(qauthz_pam_register_types); |