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