Annotation of embedaddon/strongswan/src/libcharon/plugins/ext_auth/ext_auth_listener.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (c) 2014 Vyronas Tsingaras (vtsingaras@it.auth.gr)
                      3:  * Copyright (C) 2014 Martin Willi
                      4:  * Copyright (C) 2014 revosec AG
                      5:  *
                      6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      7:  * of this software and associated documentation files (the "Software"), to deal
                      8:  * in the Software without restriction, including without limitation the rights
                      9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     10:  * copies of the Software, and to permit persons to whom the Software is
                     11:  * furnished to do so, subject to the following conditions:
                     12:  *
                     13:  * The above copyright notice and this permission notice shall be included in
                     14:  * all copies or substantial portions of the Software.
                     15:  *
                     16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
                     19:  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     22:  * THE SOFTWARE.
                     23:  */
                     24: 
                     25: /* for vasprintf() */
                     26: #define _GNU_SOURCE
                     27: #include "ext_auth_listener.h"
                     28: 
                     29: #include <daemon.h>
                     30: #include <utils/process.h>
                     31: 
                     32: #include <stdio.h>
                     33: #include <unistd.h>
                     34: 
                     35: typedef struct private_ext_auth_listener_t private_ext_auth_listener_t;
                     36: 
                     37: /**
                     38:  * Private data of an ext_auth_listener_t object.
                     39:  */
                     40: struct private_ext_auth_listener_t {
                     41: 
                     42:        /**
                     43:         * Public ext_auth_listener_listener_t interface.
                     44:         */
                     45:        ext_auth_listener_t public;
                     46: 
                     47:        /**
                     48:         * Path to authorization program
                     49:         */
                     50:        char *script;
                     51: };
                     52: 
                     53: /**
                     54:  * Allocate and push a format string to the environment
                     55:  */
                     56: static bool push_env(char *envp[], u_int count, char *fmt, ...)
                     57: {
                     58:        int i = 0;
                     59:        char *str;
                     60:        va_list args;
                     61: 
                     62:        while (envp[i])
                     63:        {
                     64:                if (++i + 1 >= count)
                     65:                {
                     66:                        return FALSE;
                     67:                }
                     68:        }
                     69:        va_start(args, fmt);
                     70:        if (vasprintf(&str, fmt, args) >= 0)
                     71:        {
                     72:                envp[i] = str;
                     73:        }
                     74:        va_end(args);
                     75:        return envp[i] != NULL;
                     76: }
                     77: 
                     78: /**
                     79:  * Free all allocated environment strings
                     80:  */
                     81: static void free_env(char *envp[])
                     82: {
                     83:        int i;
                     84: 
                     85:        for (i = 0; envp[i]; i++)
                     86:        {
                     87:                free(envp[i]);
                     88:        }
                     89: }
                     90: 
                     91: METHOD(listener_t, authorize, bool,
                     92:        private_ext_auth_listener_t *this, ike_sa_t *ike_sa,
                     93:        bool final, bool *success)
                     94: {
                     95:        if (final)
                     96:        {
                     97:                FILE *shell;
                     98:                process_t *process;
                     99:                char *envp[32] = {};
                    100:                int out, retval;
                    101: 
                    102:                *success = FALSE;
                    103: 
                    104:                push_env(envp, countof(envp), "IKE_UNIQUE_ID=%u",
                    105:                                 ike_sa->get_unique_id(ike_sa));
                    106:                push_env(envp, countof(envp), "IKE_NAME=%s",
                    107:                                 ike_sa->get_name(ike_sa));
                    108: 
                    109:                push_env(envp, countof(envp), "IKE_LOCAL_HOST=%H",
                    110:                                 ike_sa->get_my_host(ike_sa));
                    111:                push_env(envp, countof(envp), "IKE_REMOTE_HOST=%H",
                    112:                                 ike_sa->get_other_host(ike_sa));
                    113: 
                    114:                push_env(envp, countof(envp), "IKE_LOCAL_ID=%Y",
                    115:                                 ike_sa->get_my_id(ike_sa));
                    116:                push_env(envp, countof(envp), "IKE_REMOTE_ID=%Y",
                    117:                                 ike_sa->get_other_id(ike_sa));
                    118: 
                    119:                if (ike_sa->has_condition(ike_sa, COND_EAP_AUTHENTICATED) ||
                    120:                        ike_sa->has_condition(ike_sa, COND_XAUTH_AUTHENTICATED))
                    121:                {
                    122:                        push_env(envp, countof(envp), "IKE_REMOTE_EAP_ID=%Y",
                    123:                                         ike_sa->get_other_eap_id(ike_sa));
                    124:                }
                    125: 
                    126:                process = process_start_shell(envp, NULL, &out, NULL,
                    127:                                                                          "2>&1 %s", this->script);
                    128:                if (process)
                    129:                {
                    130:                        shell = fdopen(out, "r");
                    131:                        if (shell)
                    132:                        {
                    133:                                while (TRUE)
                    134:                                {
                    135:                                        char resp[128], *e;
                    136: 
                    137:                                        if (fgets(resp, sizeof(resp), shell) == NULL)
                    138:                                        {
                    139:                                                if (ferror(shell))
                    140:                                                {
                    141:                                                        DBG1(DBG_CFG, "error reading from ext-auth script");
                    142:                                                }
                    143:                                                break;
                    144:                                        }
                    145:                                        else
                    146:                                        {
                    147:                                                e = resp + strlen(resp);
                    148:                                                if (e > resp && e[-1] == '\n')
                    149:                                                {
                    150:                                                        e[-1] = '\0';
                    151:                                                }
                    152:                                                DBG1(DBG_CHD, "ext-auth: %s", resp);
                    153:                                        }
                    154:                                }
                    155:                                fclose(shell);
                    156:                        }
                    157:                        else
                    158:                        {
                    159:                                close(out);
                    160:                        }
                    161:                        if (process->wait(process, &retval))
                    162:                        {
                    163:                                if (retval == EXIT_SUCCESS)
                    164:                                {
                    165:                                        *success = TRUE;
                    166:                                }
                    167:                                else
                    168:                                {
                    169:                                        DBG1(DBG_CFG, "rejecting IKE_SA for ext-auth result: %d",
                    170:                                                 retval);
                    171:                                }
                    172:                        }
                    173:                }
                    174:                free_env(envp);
                    175:        }
                    176:        return TRUE;
                    177: }
                    178: 
                    179: METHOD(ext_auth_listener_t, destroy, void,
                    180:        private_ext_auth_listener_t *this)
                    181: {
                    182:        free(this);
                    183: }
                    184: 
                    185: /**
                    186:  * See header
                    187:  */
                    188: ext_auth_listener_t *ext_auth_listener_create(char *script)
                    189: {
                    190:        private_ext_auth_listener_t *this;
                    191: 
                    192:        INIT(this,
                    193:                .public = {
                    194:                        .listener = {
                    195:                                .authorize = _authorize,
                    196:                        },
                    197:                        .destroy = _destroy,
                    198:                },
                    199:                .script = script,
                    200:        );
                    201: 
                    202:        return &this->public;
                    203: }

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