mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-10-13 18:12:03 +08:00
This change puts a proc_st that its client has terminated to a "zombie" state. That state will allow a client that connects later using the same TLS session ID to reclaim it. That way clients that try to authenticate by sending their credentials in different sessions can still authenticate with ocserv. That however puts more trust to worker processes (as the main process has no way of telling whether a TLS session is certainly resumed).
154 lines
3.6 KiB
C
154 lines
3.6 KiB
C
/*
|
|
* Copyright (C) 2013 Nikos Mavrogiannopoulos
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include <gnutls/gnutls.h>
|
|
#include <gnutls/crypto.h>
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <limits.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include <ip-lease.h>
|
|
#include <main.h>
|
|
#include <cookies.h>
|
|
|
|
int decrypt_cookie(main_server_st * s, const uint8_t* cookie, unsigned cookie_size,
|
|
struct stored_cookie_st* sc)
|
|
{
|
|
gnutls_datum_t iv = { (void*)cookie, COOKIE_IV_SIZE };
|
|
int ret;
|
|
uint8_t tag[COOKIE_MAC_SIZE];
|
|
gnutls_cipher_hd_t h;
|
|
gnutls_datum_t key = { (void*)s->cookie_key, sizeof(s->cookie_key) };
|
|
|
|
if (cookie_size != COOKIE_SIZE)
|
|
return -1;
|
|
|
|
ret = gnutls_cipher_init(&h, GNUTLS_CIPHER_AES_128_GCM, &key, &iv);
|
|
if (ret < 0)
|
|
return -1;
|
|
|
|
cookie += COOKIE_IV_SIZE;
|
|
|
|
ret = gnutls_cipher_decrypt2(h, cookie, sizeof(*sc), sc, sizeof(*sc));
|
|
if (ret < 0) {
|
|
ret = -1;
|
|
goto cleanup;
|
|
}
|
|
|
|
ret = gnutls_cipher_tag(h, tag, sizeof(tag));
|
|
if (ret < 0) {
|
|
ret = -1;
|
|
goto cleanup;
|
|
}
|
|
|
|
cookie += sizeof(*sc);
|
|
if (memcmp(tag, cookie, COOKIE_MAC_SIZE) != 0) {
|
|
ret = -1;
|
|
goto cleanup;
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
gnutls_cipher_deinit(h);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int encrypt_cookie(main_server_st * s, const struct stored_cookie_st* sc,
|
|
uint8_t* cookie, unsigned cookie_size)
|
|
{
|
|
uint8_t _iv[COOKIE_IV_SIZE];
|
|
gnutls_cipher_hd_t h;
|
|
gnutls_datum_t iv = { _iv, sizeof(_iv) };
|
|
gnutls_datum_t key = { (void*)s->cookie_key, sizeof(s->cookie_key) };
|
|
int ret;
|
|
|
|
if (cookie_size != COOKIE_SIZE)
|
|
return -1;
|
|
|
|
ret = gnutls_rnd(GNUTLS_RND_NONCE, _iv, sizeof(_iv));
|
|
if (ret < 0)
|
|
return -1;
|
|
|
|
ret = gnutls_cipher_init(&h, GNUTLS_CIPHER_AES_128_GCM, &key, &iv);
|
|
if (ret < 0)
|
|
return -1;
|
|
|
|
memcpy(cookie, _iv, COOKIE_IV_SIZE);
|
|
cookie += COOKIE_IV_SIZE;
|
|
|
|
ret = gnutls_cipher_encrypt2(h, sc, sizeof(*sc), cookie, sizeof(*sc));
|
|
if (ret < 0) {
|
|
ret = -1;
|
|
goto cleanup;
|
|
}
|
|
|
|
cookie += sizeof(*sc);
|
|
|
|
ret = gnutls_cipher_tag(h, cookie, COOKIE_MAC_SIZE);
|
|
if (ret < 0) {
|
|
ret = -1;
|
|
goto cleanup;
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
gnutls_cipher_deinit(h);
|
|
return ret;
|
|
|
|
}
|
|
|
|
int generate_cookie(main_server_st *s, struct proc_st* proc)
|
|
{
|
|
int ret;
|
|
struct stored_cookie_st sc;
|
|
|
|
ret = gnutls_rnd(GNUTLS_RND_NONCE, proc->dtls_session_id, sizeof(proc->dtls_session_id));
|
|
if (ret < 0)
|
|
return -1;
|
|
|
|
proc->dtls_session_id_size = sizeof(proc->dtls_session_id);
|
|
|
|
memcpy(sc.username, proc->username, sizeof(proc->username));
|
|
memcpy(sc.groupname, proc->groupname, sizeof(proc->groupname));
|
|
memcpy(sc.hostname, proc->hostname, sizeof(proc->hostname));
|
|
memcpy(sc.session_id, proc->dtls_session_id, sizeof(proc->dtls_session_id));
|
|
|
|
sc.expiration = time(0) + s->config->cookie_validity;
|
|
|
|
memcpy(sc.ipv4_seed, SA_IN_U8_P(&proc->ipv4->lip), 4);
|
|
|
|
ret = encrypt_cookie(s, &sc, proc->cookie, sizeof(proc->cookie));
|
|
if (ret < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|