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); 149