Annotation of embedaddon/strongswan/src/libcharon/plugins/xauth_pam/xauth_pam.c, revision 1.1.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>