Annotation of embedaddon/strongswan/src/libcharon/plugins/xauth_pam/xauth_pam.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2012 Martin Willi
        !             3:  * Copyright (C) 2012 revosec AG
        !             4:  *
        !             5:  * This program is free software; you can redistribute it and/or modify it
        !             6:  * under the terms of the GNU General Public License as published by the
        !             7:  * Free Software Foundation; either version 2 of the License, or (at your
        !             8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !             9:  *
        !            10:  * This program is distributed in the hope that it will be useful, but
        !            11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            13:  * for more details.
        !            14:  */
        !            15: 
        !            16: #include "xauth_pam.h"
        !            17: 
        !            18: #include <daemon.h>
        !            19: #include <library.h>
        !            20: 
        !            21: #include <security/pam_appl.h>
        !            22: 
        !            23: typedef struct private_xauth_pam_t private_xauth_pam_t;
        !            24: 
        !            25: /**
        !            26:  * Private data of an xauth_pam_t object.
        !            27:  */
        !            28: struct private_xauth_pam_t {
        !            29: 
        !            30:        /**
        !            31:         * Public interface.
        !            32:         */
        !            33:        xauth_pam_t public;
        !            34: 
        !            35:        /**
        !            36:         * ID of the peer
        !            37:         */
        !            38:        identification_t *peer;
        !            39: };
        !            40: 
        !            41: METHOD(xauth_method_t, initiate, status_t,
        !            42:        private_xauth_pam_t *this, cp_payload_t **out)
        !            43: {
        !            44:        cp_payload_t *cp;
        !            45: 
        !            46:        cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REQUEST);
        !            47:        cp->add_attribute(cp, configuration_attribute_create_chunk(
        !            48:                                PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME, chunk_empty));
        !            49:        cp->add_attribute(cp, configuration_attribute_create_chunk(
        !            50:                                PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_PASSWORD, chunk_empty));
        !            51:        *out = cp;
        !            52:        return NEED_MORE;
        !            53: }
        !            54: 
        !            55: /**
        !            56:  * PAM conv callback function
        !            57:  */
        !            58: static int auth_conv(int num_msg, const struct pam_message **msg,
        !            59:                                         struct pam_response **resp, char *password)
        !            60: {
        !            61:        struct pam_response *response;
        !            62: 
        !            63:        if (num_msg != 1)
        !            64:        {
        !            65:                return PAM_CONV_ERR;
        !            66:        }
        !            67:        response = malloc(sizeof(struct pam_response));
        !            68:        response->resp = strdup(password);
        !            69:        response->resp_retcode = 0;
        !            70:        *resp = response;
        !            71:        return PAM_SUCCESS;
        !            72: }
        !            73: 
        !            74: /**
        !            75:  * Authenticate a username/password using PAM
        !            76:  */
        !            77: static bool authenticate(char *service, char *user, char *password)
        !            78: {
        !            79:        pam_handle_t *pamh = NULL;
        !            80:        static struct pam_conv conv;
        !            81:        int ret;
        !            82: 
        !            83:        conv.conv = (void*)auth_conv;
        !            84:        conv.appdata_ptr = password;
        !            85: 
        !            86:        ret = pam_start(service, user, &conv, &pamh);
        !            87:        if (ret != PAM_SUCCESS)
        !            88:        {
        !            89:                DBG1(DBG_IKE, "XAuth pam_start for '%s' failed: %s",
        !            90:                         user, pam_strerror(pamh, ret));
        !            91:                return FALSE;
        !            92:        }
        !            93:        ret = pam_authenticate(pamh, 0);
        !            94:        if (ret == PAM_SUCCESS)
        !            95:        {
        !            96:                ret = pam_acct_mgmt(pamh, 0);
        !            97:                if (ret != PAM_SUCCESS)
        !            98:                {
        !            99:                        DBG1(DBG_IKE, "XAuth pam_acct_mgmt for '%s' failed: %s",
        !           100:                                 user, pam_strerror(pamh, ret));
        !           101:                }
        !           102:        }
        !           103:        else
        !           104:        {
        !           105:                DBG1(DBG_IKE, "XAuth pam_authenticate for '%s' failed: %s",
        !           106:                         user, pam_strerror(pamh, ret));
        !           107:        }
        !           108:        pam_end(pamh, ret);
        !           109:        return ret == PAM_SUCCESS;
        !           110: }
        !           111: 
        !           112: /**
        !           113:  * Convert configuration attribute content to a null-terminated string
        !           114:  */
        !           115: static void attr2string(char *buf, size_t len, chunk_t chunk)
        !           116: {
        !           117:        if (chunk.len && chunk.len < len)
        !           118:        {
        !           119:                chunk_t sane;
        !           120: 
        !           121:                chunk_printable(chunk, &sane, '?');
        !           122:                snprintf(buf, len, "%.*s", (int)sane.len, sane.ptr);
        !           123:                chunk_clear(&sane);
        !           124:        }
        !           125: }
        !           126: 
        !           127: METHOD(xauth_method_t, process, status_t,
        !           128:        private_xauth_pam_t *this, cp_payload_t *in, cp_payload_t **out)
        !           129: {
        !           130:        char *service, user[128] = "", pass[128] = "", *pos;
        !           131:        configuration_attribute_t *attr;
        !           132:        enumerator_t *enumerator;
        !           133:        chunk_t chunk;
        !           134: 
        !           135:        enumerator = in->create_attribute_enumerator(in);
        !           136:        while (enumerator->enumerate(enumerator, &attr))
        !           137:        {
        !           138:                switch (attr->get_type(attr))
        !           139:                {
        !           140:                        case XAUTH_USER_NAME:
        !           141:                                chunk = attr->get_chunk(attr);
        !           142:                                /* trim to username part if email address given */
        !           143:                                if (lib->settings->get_bool(lib->settings,
        !           144:                                                                                        "%s.plugins.xauth-pam.trim_email",
        !           145:                                                                                        TRUE, lib->ns))
        !           146:                                {
        !           147:                                        pos = memchr(chunk.ptr, '@', chunk.len);
        !           148:                                        if (pos)
        !           149:                                        {
        !           150:                                                chunk.len = (u_char*)pos - chunk.ptr;
        !           151:                                        }
        !           152:                                }
        !           153:                                attr2string(user, sizeof(user), chunk);
        !           154:                                break;
        !           155:                        case XAUTH_USER_PASSWORD:
        !           156:                                chunk = attr->get_chunk(attr);
        !           157:                                if (chunk.len && chunk.ptr[chunk.len - 1] == 0)
        !           158:                                {       /* fix null-terminated passwords (Android etc.) */
        !           159:                                        chunk.len -= 1;
        !           160:                                }
        !           161:                                attr2string(pass, sizeof(pass), chunk);
        !           162:                                break;
        !           163:                        default:
        !           164:                                break;
        !           165:                }
        !           166:        }
        !           167:        enumerator->destroy(enumerator);
        !           168: 
        !           169:        if (!user[0] || !pass[0])
        !           170:        {
        !           171:                DBG1(DBG_IKE, "peer did not respond to our XAuth request");
        !           172:                return FAILED;
        !           173:        }
        !           174: 
        !           175:        this->peer->destroy(this->peer);
        !           176:        this->peer = identification_create_from_string(user);
        !           177: 
        !           178:        /* Look for PAM service, with a legacy fallback for the eap-gtc plugin.
        !           179:         * Default to "login". */
        !           180:        service = lib->settings->get_str(lib->settings,
        !           181:                                "%s.plugins.xauth-pam.pam_service",
        !           182:                                        lib->settings->get_str(lib->settings,
        !           183:                                                "%s.plugins.eap-gtc.pam_service", "login", lib->ns),
        !           184:                                lib->ns);
        !           185: 
        !           186:        if (authenticate(service, user, pass))
        !           187:        {
        !           188:                DBG1(DBG_IKE, "PAM authentication of '%s' successful", user);
        !           189:                return SUCCESS;
        !           190:        }
        !           191:        return FAILED;
        !           192: }
        !           193: 
        !           194: METHOD(xauth_method_t, get_identity, identification_t*,
        !           195:        private_xauth_pam_t *this)
        !           196: {
        !           197:        return this->peer;
        !           198: }
        !           199: 
        !           200: METHOD(xauth_method_t, destroy, void,
        !           201:        private_xauth_pam_t *this)
        !           202: {
        !           203:        this->peer->destroy(this->peer);
        !           204:        free(this);
        !           205: }
        !           206: 
        !           207: /*
        !           208:  * Described in header.
        !           209:  */
        !           210: xauth_pam_t *xauth_pam_create_server(identification_t *server,
        !           211:                                                                         identification_t *peer, char *profile)
        !           212: {
        !           213:        private_xauth_pam_t *this;
        !           214: 
        !           215:        INIT(this,
        !           216:                .public = {
        !           217:                        .xauth_method = {
        !           218:                                .initiate = _initiate,
        !           219:                                .process = _process,
        !           220:                                .get_identity = _get_identity,
        !           221:                                .destroy = _destroy,
        !           222:                        },
        !           223:                },
        !           224:                .peer = peer->clone(peer),
        !           225:        );
        !           226: 
        !           227:        return &this->public;
        !           228: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>