xref: /qemu/authz/pamacct.c (revision 3428455d)
18953caf3SDaniel P. Berrange /*
28953caf3SDaniel P. Berrange  * QEMU PAM authorization driver
38953caf3SDaniel P. Berrange  *
48953caf3SDaniel P. Berrange  * Copyright (c) 2018 Red Hat, Inc.
58953caf3SDaniel P. Berrange  *
68953caf3SDaniel P. Berrange  * This library is free software; you can redistribute it and/or
78953caf3SDaniel P. Berrange  * modify it under the terms of the GNU Lesser General Public
88953caf3SDaniel P. Berrange  * License as published by the Free Software Foundation; either
9036a80cdSChetan Pant  * version 2.1 of the License, or (at your option) any later version.
108953caf3SDaniel P. Berrange  *
118953caf3SDaniel P. Berrange  * This library is distributed in the hope that it will be useful,
128953caf3SDaniel P. Berrange  * but WITHOUT ANY WARRANTY; without even the implied warranty of
138953caf3SDaniel P. Berrange  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
148953caf3SDaniel P. Berrange  * Lesser General Public License for more details.
158953caf3SDaniel P. Berrange  *
168953caf3SDaniel P. Berrange  * You should have received a copy of the GNU Lesser General Public
178953caf3SDaniel P. Berrange  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
188953caf3SDaniel P. Berrange  *
198953caf3SDaniel P. Berrange  */
208953caf3SDaniel P. Berrange 
218953caf3SDaniel P. Berrange #include "qemu/osdep.h"
228953caf3SDaniel P. Berrange #include "authz/pamacct.h"
2345b1f68cSMarkus Armbruster #include "trace.h"
240b8fa32fSMarkus Armbruster #include "qemu/module.h"
258953caf3SDaniel P. Berrange #include "qom/object_interfaces.h"
268953caf3SDaniel P. Berrange 
278953caf3SDaniel P. Berrange #include <security/pam_appl.h>
288953caf3SDaniel P. Berrange 
298953caf3SDaniel P. Berrange 
qauthz_pam_is_allowed(QAuthZ * authz,const char * identity,Error ** errp)308953caf3SDaniel P. Berrange static bool qauthz_pam_is_allowed(QAuthZ *authz,
318953caf3SDaniel P. Berrange                                   const char *identity,
328953caf3SDaniel P. Berrange                                   Error **errp)
338953caf3SDaniel P. Berrange {
348953caf3SDaniel P. Berrange     QAuthZPAM *pauthz = QAUTHZ_PAM(authz);
358953caf3SDaniel P. Berrange     const struct pam_conv pam_conversation = { 0 };
368953caf3SDaniel P. Berrange     pam_handle_t *pamh = NULL;
378953caf3SDaniel P. Berrange     int ret;
388953caf3SDaniel P. Berrange 
398953caf3SDaniel P. Berrange     trace_qauthz_pam_check(authz, identity, pauthz->service);
408953caf3SDaniel P. Berrange     ret = pam_start(pauthz->service,
418953caf3SDaniel P. Berrange                     identity,
428953caf3SDaniel P. Berrange                     &pam_conversation,
438953caf3SDaniel P. Berrange                     &pamh);
448953caf3SDaniel P. Berrange     if (ret != PAM_SUCCESS) {
458953caf3SDaniel P. Berrange         error_setg(errp, "Unable to start PAM transaction: %s",
468953caf3SDaniel P. Berrange                    pam_strerror(NULL, ret));
478953caf3SDaniel P. Berrange         return false;
488953caf3SDaniel P. Berrange     }
498953caf3SDaniel P. Berrange 
508953caf3SDaniel P. Berrange     ret = pam_acct_mgmt(pamh, PAM_SILENT);
518953caf3SDaniel P. Berrange     pam_end(pamh, ret);
528953caf3SDaniel P. Berrange     if (ret != PAM_SUCCESS) {
538953caf3SDaniel P. Berrange         error_setg(errp, "Unable to authorize user '%s': %s",
548953caf3SDaniel P. Berrange                    identity, pam_strerror(pamh, ret));
558953caf3SDaniel P. Berrange         return false;
568953caf3SDaniel P. Berrange     }
578953caf3SDaniel P. Berrange 
588953caf3SDaniel P. Berrange     return true;
598953caf3SDaniel P. Berrange }
608953caf3SDaniel P. Berrange 
618953caf3SDaniel P. Berrange 
628953caf3SDaniel P. Berrange static void
qauthz_pam_prop_set_service(Object * obj,const char * service,Error ** errp G_GNUC_UNUSED)638953caf3SDaniel P. Berrange qauthz_pam_prop_set_service(Object *obj,
648953caf3SDaniel P. Berrange                             const char *service,
658953caf3SDaniel P. Berrange                             Error **errp G_GNUC_UNUSED)
668953caf3SDaniel P. Berrange {
678953caf3SDaniel P. Berrange     QAuthZPAM *pauthz = QAUTHZ_PAM(obj);
688953caf3SDaniel P. Berrange 
698953caf3SDaniel P. Berrange     g_free(pauthz->service);
708953caf3SDaniel P. Berrange     pauthz->service = g_strdup(service);
718953caf3SDaniel P. Berrange }
728953caf3SDaniel P. Berrange 
738953caf3SDaniel P. Berrange 
748953caf3SDaniel P. Berrange static char *
qauthz_pam_prop_get_service(Object * obj,Error ** errp G_GNUC_UNUSED)758953caf3SDaniel P. Berrange qauthz_pam_prop_get_service(Object *obj,
768953caf3SDaniel P. Berrange                             Error **errp G_GNUC_UNUSED)
778953caf3SDaniel P. Berrange {
788953caf3SDaniel P. Berrange     QAuthZPAM *pauthz = QAUTHZ_PAM(obj);
798953caf3SDaniel P. Berrange 
808953caf3SDaniel P. Berrange     return g_strdup(pauthz->service);
818953caf3SDaniel P. Berrange }
828953caf3SDaniel P. Berrange 
838953caf3SDaniel P. Berrange 
848953caf3SDaniel P. Berrange static void
qauthz_pam_complete(UserCreatable * uc,Error ** errp)858953caf3SDaniel P. Berrange qauthz_pam_complete(UserCreatable *uc, Error **errp)
868953caf3SDaniel P. Berrange {
87*3428455dSKevin Wolf     QAuthZPAM *pauthz = QAUTHZ_PAM(uc);
88*3428455dSKevin Wolf 
89*3428455dSKevin Wolf     if (!pauthz->service) {
90*3428455dSKevin Wolf         error_setg(errp, "The 'service' property must be set");
91*3428455dSKevin Wolf         return;
92*3428455dSKevin Wolf     }
938953caf3SDaniel P. Berrange }
948953caf3SDaniel P. Berrange 
958953caf3SDaniel P. Berrange 
968953caf3SDaniel P. Berrange static void
qauthz_pam_finalize(Object * obj)978953caf3SDaniel P. Berrange qauthz_pam_finalize(Object *obj)
988953caf3SDaniel P. Berrange {
998953caf3SDaniel P. Berrange     QAuthZPAM *pauthz = QAUTHZ_PAM(obj);
1008953caf3SDaniel P. Berrange 
1018953caf3SDaniel P. Berrange     g_free(pauthz->service);
1028953caf3SDaniel P. Berrange }
1038953caf3SDaniel P. Berrange 
1048953caf3SDaniel P. Berrange 
1058953caf3SDaniel P. Berrange static void
qauthz_pam_class_init(ObjectClass * oc,void * data)1068953caf3SDaniel P. Berrange qauthz_pam_class_init(ObjectClass *oc, void *data)
1078953caf3SDaniel P. Berrange {
1088953caf3SDaniel P. Berrange     UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
1098953caf3SDaniel P. Berrange     QAuthZClass *authz = QAUTHZ_CLASS(oc);
1108953caf3SDaniel P. Berrange 
1118953caf3SDaniel P. Berrange     ucc->complete = qauthz_pam_complete;
1128953caf3SDaniel P. Berrange     authz->is_allowed = qauthz_pam_is_allowed;
1138953caf3SDaniel P. Berrange 
1148953caf3SDaniel P. Berrange     object_class_property_add_str(oc, "service",
1158953caf3SDaniel P. Berrange                                   qauthz_pam_prop_get_service,
116d2623129SMarkus Armbruster                                   qauthz_pam_prop_set_service);
1178953caf3SDaniel P. Berrange }
1188953caf3SDaniel P. Berrange 
1198953caf3SDaniel P. Berrange 
qauthz_pam_new(const char * id,const char * service,Error ** errp)1208953caf3SDaniel P. Berrange QAuthZPAM *qauthz_pam_new(const char *id,
1218953caf3SDaniel P. Berrange                           const char *service,
1228953caf3SDaniel P. Berrange                           Error **errp)
1238953caf3SDaniel P. Berrange {
1248953caf3SDaniel P. Berrange     return QAUTHZ_PAM(
1258953caf3SDaniel P. Berrange         object_new_with_props(TYPE_QAUTHZ_PAM,
1268953caf3SDaniel P. Berrange                               object_get_objects_root(),
1278953caf3SDaniel P. Berrange                               id, errp,
1288953caf3SDaniel P. Berrange                               "service", service,
1298953caf3SDaniel P. Berrange                               NULL));
1308953caf3SDaniel P. Berrange }
1318953caf3SDaniel P. Berrange 
1328953caf3SDaniel P. Berrange 
1338953caf3SDaniel P. Berrange static const TypeInfo qauthz_pam_info = {
1348953caf3SDaniel P. Berrange     .parent = TYPE_QAUTHZ,
1358953caf3SDaniel P. Berrange     .name = TYPE_QAUTHZ_PAM,
1368953caf3SDaniel P. Berrange     .instance_size = sizeof(QAuthZPAM),
1378953caf3SDaniel P. Berrange     .instance_finalize = qauthz_pam_finalize,
1388953caf3SDaniel P. Berrange     .class_init = qauthz_pam_class_init,
1398953caf3SDaniel P. Berrange     .interfaces = (InterfaceInfo[]) {
1408953caf3SDaniel P. Berrange         { TYPE_USER_CREATABLE },
1418953caf3SDaniel P. Berrange         { }
1428953caf3SDaniel P. Berrange     }
1438953caf3SDaniel P. Berrange };
1448953caf3SDaniel P. Berrange 
1458953caf3SDaniel P. Berrange 
1468953caf3SDaniel P. Berrange static void
qauthz_pam_register_types(void)1478953caf3SDaniel P. Berrange qauthz_pam_register_types(void)
1488953caf3SDaniel P. Berrange {
1498953caf3SDaniel P. Berrange     type_register_static(&qauthz_pam_info);
1508953caf3SDaniel P. Berrange }
1518953caf3SDaniel P. Berrange 
1528953caf3SDaniel P. Berrange 
1538953caf3SDaniel P. Berrange type_init(qauthz_pam_register_types);
154