mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 00:37:00 +08:00
Use PAM account management and added support for user groups.
This commit is contained in:
299
doc/ocserv.1
Normal file
299
doc/ocserv.1
Normal file
@@ -0,0 +1,299 @@
|
||||
.TH ocserv 1 "12 Feb 2013" "" "User Commands"
|
||||
.\"
|
||||
.\" DO NOT EDIT THIS FILE (ocserv-args.man)
|
||||
.\"
|
||||
.\" It has been AutoGen-ed February 12, 2013 at 04:34:58 PM by AutoGen 5.16
|
||||
.\" From the definitions ../src/ocserv-args.def.tmp
|
||||
.\" and the template file agman-cmd.tpl
|
||||
.\"
|
||||
.SH NAME
|
||||
ocserv \- OpenConnect server
|
||||
.SH SYNOPSIS
|
||||
.B ocserv
|
||||
.\" Mixture of short (flag) options and long options
|
||||
.RB [ \-\fIflag\fP " [\fIvalue\fP]]... [" \-\-\fIopt\-name\fP " [[=| ]\fIvalue\fP]]..."
|
||||
.PP
|
||||
All arguments must be options.
|
||||
.PP
|
||||
.SH "DESCRIPTION"
|
||||
This program is openconnect VPN server (ocserv), a server compatible with the
|
||||
openconnect VPN client. It is believed to be compatible with the protocol
|
||||
used by CISCO's AnyConnect SSL VPN.
|
||||
.SH "OPTIONS"
|
||||
.TP
|
||||
.BR \-f ", " -\-foreground
|
||||
Do not fork into background.
|
||||
.sp
|
||||
.TP
|
||||
.BR \-\-tls\-debug
|
||||
Enable verbose TLS debugging information.
|
||||
.sp
|
||||
.TP
|
||||
.BR \-d ", " -\-debug
|
||||
Enable verbose network debugging information.
|
||||
.sp
|
||||
.TP
|
||||
.BR \-c " \fIfile\fP, " \-\-config "=" \fIfile\fP
|
||||
Configuration file for the server.
|
||||
.sp
|
||||
.TP
|
||||
.BR \-h , " \-\-help"
|
||||
Display usage information and exit.
|
||||
.TP
|
||||
.BR \-! , " \-\-more-help"
|
||||
Pass the extended usage information through a pager.
|
||||
.SH AUTHENTICATION
|
||||
.br
|
||||
\fBPassword authentication\fP
|
||||
.br
|
||||
If your system supports Pluggable Authentication Modules (PAM), then
|
||||
ocserv will take advantage of it to password authenticate its users.
|
||||
It can be used in conjunction with certificate authentication.
|
||||
.sp
|
||||
.br
|
||||
\fBCertificate authentication\fP
|
||||
.br
|
||||
In order to support certificate authentication you will need in addition to
|
||||
the server certificate and key for TLS, a certificate authority (CA) to sign
|
||||
certificates for the clients. That authority should also provide a CRL to
|
||||
allow the server to reject the revoked clients (see \fBca\-cert, crl\fP).
|
||||
.sp
|
||||
Each client will then hold a key and certificate that identifies him.
|
||||
The user ID of the client must be embedded in the certificate's Distinguished
|
||||
Name (DN), e.g. in the Common Name, or UID fields. For the server to
|
||||
read the name, the \fBcert\-user\-oid\fP configuration option must be set.
|
||||
.sp
|
||||
The following examples demonstrate how to use certtool from GnuTLS to
|
||||
generate such CA.
|
||||
.sp
|
||||
.br
|
||||
\fBGenerating the CA\fP
|
||||
.br
|
||||
.br
|
||||
.in +4
|
||||
.nf
|
||||
$ certtool \-\-generate\-privkey \-\-outfile ca\-key.pem
|
||||
$ cat << _EOF_ >ca.tmpl
|
||||
cn = "VPN CA"
|
||||
organization = "Big Corp"
|
||||
serial = 1
|
||||
expiration_days = 9999
|
||||
ca
|
||||
signing_key
|
||||
cert_signing_key
|
||||
crl_signing_key
|
||||
_EOF_
|
||||
$ certtool \-\-generate\-self\-signed \-\-load\-privkey ca\-key.pem \
|
||||
-\-template ca.tmpl \-\-outfile ca\-cert.pem
|
||||
.in -4
|
||||
.fi
|
||||
.sp
|
||||
.br
|
||||
\fBGenerating the client certificates\fP
|
||||
.br
|
||||
.br
|
||||
.in +4
|
||||
.nf
|
||||
$ certtool \-\-generate\-privkey \-\-outfile user\-key.pem
|
||||
$ cat << _EOF_ >user.tmpl
|
||||
cn = "user"
|
||||
serial = 1824
|
||||
email = "user@example.com"
|
||||
expiration_days = 9999
|
||||
signing_key
|
||||
tls_www_client
|
||||
_EOF_
|
||||
$ certtool \-\-generate\-certificate \-\-load\-privkey user\-key.pem \
|
||||
-\-load\-ca\-certificate ca\-cert.pem \-\-load\-ca\-privkey ca\-key.pem \
|
||||
-\-template user.tmpl \-\-outfile user\-cert.pem
|
||||
.sp
|
||||
.in -4
|
||||
.fi
|
||||
.sp
|
||||
.br
|
||||
\fBRevoking a client certificate\fP
|
||||
.br
|
||||
To revoke the previous client certificate use:
|
||||
.br
|
||||
.in +4
|
||||
.nf
|
||||
$ cat user\-cert.pem >>revoked.pem
|
||||
$ certtool \-\-generate\-crl \-\-load\-ca\-privkey ca\-key.pem \
|
||||
-\-load\-ca\-certificate ca.pem \-\-load\-certificate revoked.pem \
|
||||
-\-outfile crl.pem
|
||||
.in -4
|
||||
.fi
|
||||
After that you may want to notify ocserv of the new CRL by using
|
||||
the HUP signal.
|
||||
.sp
|
||||
.SH "IMPLEMENTATION NOTES"
|
||||
Note that while this server utilizes privilege separation for password
|
||||
authentication, this does not occur for TLS and client certificate authentication.
|
||||
This was done to take advantage of multi\-core systems by distributing the
|
||||
expensive TLS calculations to the workers.
|
||||
.SH FILES
|
||||
.br
|
||||
\fBocserv's configuration file format\fP
|
||||
.br
|
||||
By default, if no other file is specified, ocserv looks for its configuration file at \fI/etc/ocserv.conf\fP.
|
||||
An example configuration file follows.
|
||||
.sp
|
||||
.br
|
||||
.in +4
|
||||
.nf
|
||||
.sp
|
||||
# User authentication method. Could be set multiple times and in that case
|
||||
# all should succeed.
|
||||
# Options: certificate, pam.
|
||||
#auth = "certificate"
|
||||
auth = "pam"
|
||||
.sp
|
||||
# Use listen\-host to limit to specific IPs or to the IPs of a provided hostname.
|
||||
#listen\-host = [IP|HOSTNAME]
|
||||
.sp
|
||||
# Limit the number of clients. Unset or set to zero for unlimited.
|
||||
#max\-clients = 1024
|
||||
max\-clients = 16
|
||||
.sp
|
||||
# Limit the number of identical clients (i.e., users connecting multiple times)
|
||||
# Unset or set to zero for unlimited.
|
||||
max\-same\-clients = 1
|
||||
.sp
|
||||
# TCP and UDP port number
|
||||
tcp\-port = 3333
|
||||
udp\-port = 3333
|
||||
.sp
|
||||
# Keepalive in seconds
|
||||
keepalive = 3600
|
||||
.sp
|
||||
# Dead peer detection in seconds
|
||||
dpd = 60
|
||||
.sp
|
||||
# The key and the certificates of the server
|
||||
# The key may be a file, or any URL supported by GnuTLS (i.e., tpmkey or pkcs11)
|
||||
server\-cert = /path/to/cert.pem
|
||||
server\-key = /path/to/key.pem
|
||||
.sp
|
||||
# The Certificate Authority that will be used
|
||||
# to verify clients if certificate authentication
|
||||
# is set.
|
||||
#ca\-cert = /path/to/ca.pem
|
||||
.sp
|
||||
# The object identifier that will be used to read the user ID in the client certificate.
|
||||
# The object identifier should be part of the certificate's DN
|
||||
# Useful OIDs are:
|
||||
# CN = 2.5.4.3, UID = 0.9.2342.19200300.100.1.1
|
||||
#cert\-user\-oid = 0.9.2342.19200300.100.1.1
|
||||
.sp
|
||||
# The object identifier that will be used to read the user group in the client
|
||||
# certificate. The object identifier should be part of the certificate's DN
|
||||
# Useful OIDs are:
|
||||
# OU (organizational unit) = 2.5.4.11
|
||||
#cert\-group\-oid = 2.5.4.11
|
||||
.sp
|
||||
# A revocation list of ca\-cert is set
|
||||
#crl = /path/to/crl.pem
|
||||
.sp
|
||||
# GnuTLS priority string
|
||||
tls\-priorities = "PERFORMANCE:%SERVER_PRECEDENCE"
|
||||
.sp
|
||||
# The default server directory
|
||||
#chroot\-dir = /path/to/chroot
|
||||
.sp
|
||||
# The time (in seconds) that a client is allowed to stay connected prior
|
||||
# to authentication
|
||||
auth\-timeout = 40
|
||||
.sp
|
||||
# Cookie validity time (in seconds)
|
||||
# Once a client is authenticated he's provided a cookie with
|
||||
# which he can reconnect. This option sets the maximum lifetime
|
||||
# of that cookie.
|
||||
cookie\-validity = 14400
|
||||
.sp
|
||||
# A cookie database. If not set cookies are stored in memory and
|
||||
# server restarts won't preserve them.
|
||||
#cookie\-db = /var/tmp/cookies.db
|
||||
.sp
|
||||
# Script to call when a client connects and obtains an IP
|
||||
# Parameters: username groupname hostname device IP\-REAL IP\-LOCAL IP\-REMOTE
|
||||
# hostname is the hostname selected by the client
|
||||
# IP\-REAL is the remote IP of the client,
|
||||
# IP\-LOCAL is the local IP in the P\-t\-P connection and IP\-REMOTE
|
||||
# is the VPN client IP.
|
||||
connect\-script = /bin/echo
|
||||
disconnect\-script = /bin/echo
|
||||
.sp
|
||||
# UTMP
|
||||
use\-utmp = true
|
||||
.sp
|
||||
# PID file
|
||||
pid\-file = /var/run/ocserv.pid
|
||||
.sp
|
||||
run\-as\-user = nobody
|
||||
run\-as\-group = nogroup
|
||||
.sp
|
||||
# Network settings
|
||||
.sp
|
||||
device = vpns
|
||||
.sp
|
||||
ipv4\-network = 192.168.1.0
|
||||
ipv4\-netmask = 255.255.255.0
|
||||
# Use the keywork local to advertize the local P\-t\-P address as DNS server
|
||||
# ipv4\-dns = 192.168.2.1
|
||||
ipv4\-dns = local
|
||||
.sp
|
||||
#ipv6\-address =
|
||||
#ipv6\-mask =
|
||||
#ipv6\-dns =
|
||||
.sp
|
||||
# Leave empty to assign the default MTU of the device
|
||||
# mtu =
|
||||
.sp
|
||||
route = 192.168.1.0/255.255.255.0
|
||||
route = 192.168.5.0/255.255.255.0
|
||||
.sp
|
||||
.in -4
|
||||
.fi
|
||||
.sp
|
||||
.SH "EXIT STATUS"
|
||||
One of the following exit values will be returned:
|
||||
.TP
|
||||
.BR 0 " (EXIT_SUCCESS)"
|
||||
Successful program execution.
|
||||
.TP
|
||||
.BR 1 " (EXIT_FAILURE)"
|
||||
The operation failed or the command syntax was not valid.
|
||||
.SH COMPATIBILITY
|
||||
.br
|
||||
\fBFeatures of the server\fP
|
||||
.br
|
||||
.in +4
|
||||
.ti -4
|
||||
\fB*\fP
|
||||
Supports both TCP and UDP VPN tunnels using TLS and DTLS.
|
||||
.ti -4
|
||||
\fB*\fP
|
||||
Support for the server key being stored in TPM, a hardware security module (HSM), or smart card.
|
||||
.ti -4
|
||||
\fB*\fP
|
||||
Authentication using PAM (username\-password) or certificates
|
||||
.ti -4
|
||||
\fB*\fP
|
||||
Privilege separation between the main process which performs TUN allocation and authentication, with the worker processes which handles messages from the client.
|
||||
.ti -4
|
||||
\fB*\fP
|
||||
Registers VPN leases to UTMP and WTMP files.
|
||||
.ti -4
|
||||
\fB*\fP
|
||||
Persistent storage of cookies, to allow a seamless server restart.
|
||||
.in -4
|
||||
.SH "AUTHORS"
|
||||
Nikos Mavrogiannopoulos
|
||||
.SH "COPYRIGHT"
|
||||
Copyright (C) 2013 Nikos Mavrogiannopoulos all rights reserved.
|
||||
This program is released under the terms of the GNU General Public License, version 2.
|
||||
.SH "BUGS"
|
||||
Please send bug reports to: nmav@gnutls.org
|
||||
.SH "NOTES"
|
||||
This manual page was \fIAutoGen\fP-erated from the \fBocserv\fP
|
||||
option definitions.
|
||||
@@ -146,6 +146,7 @@ unsigned j;
|
||||
READ_STRING("ca-cert", config->ca, 0);
|
||||
READ_STRING("crl", config->crl, 0);
|
||||
READ_STRING("cert-user-oid", config->cert_user_oid, 0);
|
||||
READ_STRING("cert-group-oid", config->cert_group_oid, 0);
|
||||
|
||||
READ_STRING("connect-script", config->connect_script, 0);
|
||||
READ_STRING("disconnect-script", config->disconnect_script, 0);
|
||||
@@ -274,6 +275,7 @@ unsigned i;
|
||||
DEL(config->ca);
|
||||
DEL(config->crl);
|
||||
DEL(config->cert_user_oid);
|
||||
DEL(config->cert_group_oid);
|
||||
DEL(config->priorities);
|
||||
DEL(config->chroot_dir);
|
||||
DEL(config->cookie_db_name);
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
struct stored_cookie_st {
|
||||
uint8_t cookie[COOKIE_SIZE];
|
||||
char username[MAX_USERNAME_SIZE];
|
||||
char hostname[MAX_USERNAME_SIZE];
|
||||
char groupname[MAX_GROUPNAME_SIZE];
|
||||
char hostname[MAX_HOSTNAME_SIZE];
|
||||
uint8_t session_id[GNUTLS_MAX_SESSION_ID];
|
||||
time_t expiration;
|
||||
};
|
||||
|
||||
@@ -38,6 +38,7 @@ struct __attribute__ ((__packed__)) cmd_auth_cookie_req_st {
|
||||
uint8_t cookie[COOKIE_SIZE];
|
||||
uint8_t tls_auth_ok;
|
||||
char cert_user[MAX_USERNAME_SIZE];
|
||||
char cert_group[MAX_GROUPNAME_SIZE];
|
||||
};
|
||||
|
||||
/* AUTH_REQ */
|
||||
@@ -47,6 +48,7 @@ struct __attribute__ ((__packed__)) cmd_auth_req_st {
|
||||
char pass[MAX_PASSWORD_SIZE];
|
||||
uint8_t tls_auth_ok;
|
||||
char cert_user[MAX_USERNAME_SIZE];
|
||||
char cert_group[MAX_GROUPNAME_SIZE];
|
||||
char hostname[MAX_HOSTNAME_SIZE];
|
||||
};
|
||||
|
||||
|
||||
@@ -112,15 +112,27 @@ struct stored_cookie_st sc;
|
||||
|
||||
memcpy(proc->cookie, req->cookie, sizeof(proc->cookie));
|
||||
memcpy(proc->username, sc.username, sizeof(proc->username));
|
||||
memcpy(proc->groupname, sc.groupname, sizeof(proc->groupname));
|
||||
memcpy(proc->hostname, sc.hostname, sizeof(proc->hostname));
|
||||
memcpy(proc->session_id, sc.session_id, sizeof(proc->session_id));
|
||||
proc->session_id_size = sizeof(proc->session_id);
|
||||
|
||||
|
||||
if (req->tls_auth_ok != 0) {
|
||||
if (strcmp(proc->username, req->cert_user) != 0) {
|
||||
mslog(s, proc, LOG_INFO, "user '%s' presented a certificate from user '%s'", proc->username, req->cert_user);
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(proc->groupname, req->cert_group) != 0) {
|
||||
mslog(s, proc, LOG_INFO, "user '%s' presented a certificate from group '%s' but he is member of '%s'", proc->username, req->cert_group, proc->groupname);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ret = open_tun(s, lease);
|
||||
if (ret < 0)
|
||||
ret = -1; /* sorry */
|
||||
return -1; /* sorry */
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int generate_and_store_vals(main_server_st *s, struct proc_st* proc)
|
||||
@@ -144,6 +156,7 @@ struct stored_cookie_st *sc;
|
||||
|
||||
memcpy(sc->cookie, proc->cookie, sizeof(proc->cookie));
|
||||
memcpy(sc->username, proc->username, sizeof(sc->username));
|
||||
memcpy(sc->groupname, proc->groupname, sizeof(sc->groupname));
|
||||
memcpy(sc->hostname, proc->hostname, sizeof(sc->hostname));
|
||||
memcpy(sc->session_id, proc->session_id, sizeof(sc->session_id));
|
||||
|
||||
@@ -165,7 +178,7 @@ unsigned username_set = 0;
|
||||
|
||||
#ifdef HAVE_PAM
|
||||
if (req->user_pass_present != 0 && s->config->auth_types & AUTH_TYPE_PAM) {
|
||||
ret = pam_auth_user(req->user, req->pass);
|
||||
ret = pam_auth_user(req->user, req->pass, proc->groupname, sizeof(proc->groupname));
|
||||
if (ret != 0)
|
||||
ret = -1;
|
||||
|
||||
@@ -179,11 +192,16 @@ unsigned username_set = 0;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (username_set == 0)
|
||||
memcpy(proc->username, req->cert_user, MAX_USERNAME_SIZE);
|
||||
else {
|
||||
if (username_set == 0) {
|
||||
memcpy(proc->username, req->cert_user, sizeof(proc->username));
|
||||
memcpy(proc->groupname, req->cert_group, sizeof(proc->groupname));
|
||||
} else {
|
||||
if (strcmp(proc->username, req->cert_user) != 0) {
|
||||
mslog(s, proc, LOG_INFO, "User '%s' presented a certificate from user '%s'", proc->username, req->cert_user);
|
||||
mslog(s, proc, LOG_INFO, "user '%s' presented a certificate from user '%s'", proc->username, req->cert_user);
|
||||
ret = -1;
|
||||
}
|
||||
if (strcmp(proc->groupname, req->cert_group) != 0) {
|
||||
mslog(s, proc, LOG_INFO, "user '%s' presented a certificate from group '%s' but he is member of '%s'", proc->username, req->cert_group, proc->groupname);
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +112,6 @@ int handle_commands(main_server_st *s, struct proc_st* proc)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
char buf[128];
|
||||
int e;
|
||||
uint8_t cmd;
|
||||
struct msghdr hdr;
|
||||
struct lease_st *lease;
|
||||
@@ -123,8 +122,8 @@ int handle_commands(main_server_st *s, struct proc_st* proc)
|
||||
struct cmd_resume_fetch_req_st fresume;
|
||||
struct cmd_tun_mtu_st tmtu;
|
||||
} cmd_data;
|
||||
int ret, cmd_data_len;
|
||||
const char* peer_ip;
|
||||
int ret, cmd_data_len, e;
|
||||
const char* peer_ip, *group;
|
||||
|
||||
peer_ip = human_addr((void*)&proc->remote_addr, proc->remote_addr_len, buf, sizeof(buf));
|
||||
|
||||
@@ -143,7 +142,7 @@ int handle_commands(main_server_st *s, struct proc_st* proc)
|
||||
ret = recvmsg( proc->fd, &hdr, 0);
|
||||
if (ret == -1) {
|
||||
e = errno;
|
||||
mslog(s, proc, LOG_ERR, "Cannot obtain data from command socket (pid: %d, peer: %s): %s", proc->pid, peer_ip, strerror(e));
|
||||
mslog(s, proc, LOG_ERR, "cannot obtain data from command socket (pid: %d, peer: %s): %s", proc->pid, peer_ip, strerror(e));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -156,7 +155,7 @@ int handle_commands(main_server_st *s, struct proc_st* proc)
|
||||
switch(cmd) {
|
||||
case CMD_TUN_MTU:
|
||||
if (cmd_data_len != sizeof(cmd_data.tmtu)) {
|
||||
mslog(s, proc, LOG_ERR, "Error in received message (%u) length (pid: %d, peer: %s).", (unsigned)cmd, proc->pid, peer_ip);
|
||||
mslog(s, proc, LOG_ERR, "error in received message (%u) length (pid: %d, peer: %s).", (unsigned)cmd, proc->pid, peer_ip);
|
||||
return -2;
|
||||
}
|
||||
|
||||
@@ -165,24 +164,24 @@ int handle_commands(main_server_st *s, struct proc_st* proc)
|
||||
|
||||
case RESUME_STORE_REQ:
|
||||
if (cmd_data_len <= sizeof(cmd_data.sresume)-MAX_SESSION_DATA_SIZE) {
|
||||
mslog(s, proc, LOG_ERR, "Error in received message (%u) length (pid: %d, peer: %s).", (unsigned)cmd, proc->pid, peer_ip);
|
||||
mslog(s, proc, LOG_ERR, "error in received message (%u) length (pid: %d, peer: %s).", (unsigned)cmd, proc->pid, peer_ip);
|
||||
return -2;
|
||||
}
|
||||
ret = handle_resume_store_req(s, proc, &cmd_data.sresume);
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_DEBUG, "Could not store resumption data (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
mslog(s, proc, LOG_DEBUG, "could not store resumption data (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RESUME_DELETE_REQ:
|
||||
if (cmd_data_len != sizeof(cmd_data.fresume)) {
|
||||
mslog(s, proc, LOG_ERR, "Error in received message (%u) length (pid: %d, peer: %s).", (unsigned)cmd, proc->pid, peer_ip);
|
||||
mslog(s, proc, LOG_ERR, "error in received message (%u) length (pid: %d, peer: %s).", (unsigned)cmd, proc->pid, peer_ip);
|
||||
return -2;
|
||||
}
|
||||
ret = handle_resume_delete_req(s, proc, &cmd_data.fresume);
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_DEBUG, "Could not delete resumption data (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
mslog(s, proc, LOG_DEBUG, "could not delete resumption data (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -190,19 +189,19 @@ int handle_commands(main_server_st *s, struct proc_st* proc)
|
||||
struct cmd_resume_fetch_reply_st reply;
|
||||
|
||||
if (cmd_data_len != sizeof(cmd_data.fresume)) {
|
||||
mslog(s, proc, LOG_ERR, "Error in received message (%u) length (pid: %d, peer: %s).", (unsigned)cmd, proc->pid, peer_ip);
|
||||
mslog(s, proc, LOG_ERR, "error in received message (%u) length (pid: %d, peer: %s).", (unsigned)cmd, proc->pid, peer_ip);
|
||||
return -2;
|
||||
}
|
||||
ret = handle_resume_fetch_req(s, proc, &cmd_data.fresume, &reply);
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_DEBUG, "Could not fetch resumption data (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
mslog(s, proc, LOG_DEBUG, "could not fetch resumption data (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
ret = send_resume_fetch_reply(s, proc, REP_RESUME_FAILED, NULL);
|
||||
} else
|
||||
ret = send_resume_fetch_reply(s, proc, REP_RESUME_OK, &reply);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_ERR, "Could not send reply cmd (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
mslog(s, proc, LOG_ERR, "could not send reply cmd (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
return -2;
|
||||
}
|
||||
|
||||
@@ -214,14 +213,14 @@ int handle_commands(main_server_st *s, struct proc_st* proc)
|
||||
|
||||
if (cmd == AUTH_REQ) {
|
||||
if (cmd_data_len != sizeof(cmd_data.auth)) {
|
||||
mslog(s, proc, LOG_ERR, "Error in received message (%u) length (pid: %d, peer: %s).", (unsigned)cmd, proc->pid, peer_ip);
|
||||
mslog(s, proc, LOG_ERR, "error in received message (%u) length (pid: %d, peer: %s).", (unsigned)cmd, proc->pid, peer_ip);
|
||||
return -2;
|
||||
}
|
||||
|
||||
ret = handle_auth_req(s, proc, &cmd_data.auth, &lease);
|
||||
} else {
|
||||
if (cmd_data_len != sizeof(cmd_data.cauth)) {
|
||||
mslog(s, proc, LOG_ERR, "Error in received message (%u) length (pid: %d, peer: %s).", (unsigned)cmd, proc->pid, peer_ip);
|
||||
mslog(s, proc, LOG_ERR, "error in received message (%u) length (pid: %d, peer: %s).", (unsigned)cmd, proc->pid, peer_ip);
|
||||
return -2;
|
||||
}
|
||||
|
||||
@@ -232,19 +231,24 @@ int handle_commands(main_server_st *s, struct proc_st* proc)
|
||||
/* check for multiple connections */
|
||||
ret = check_multiple_users(s, proc);
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_INFO, "User '%s' tried to connect more than %u times", proc->username, s->config->max_same_clients);
|
||||
mslog(s, proc, LOG_INFO, "user '%s' tried to connect more than %u times", proc->username, s->config->max_same_clients);
|
||||
}
|
||||
|
||||
/* do scripts and utmp */
|
||||
if (ret == 0) {
|
||||
ret = user_connected(s, proc, lease);
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_INFO, "User '%s' disconnected due to script", proc->username);
|
||||
mslog(s, proc, LOG_INFO, "user '%s' disconnected due to script", proc->username);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
if (proc->groupname[0] == 0)
|
||||
group = "[unknown]";
|
||||
else
|
||||
group = proc->groupname;
|
||||
|
||||
if (cmd == AUTH_REQ) {
|
||||
/* generate and store cookie */
|
||||
ret = generate_and_store_vals(s, proc);
|
||||
@@ -252,14 +256,14 @@ int handle_commands(main_server_st *s, struct proc_st* proc)
|
||||
ret = -2;
|
||||
goto lease_cleanup;
|
||||
}
|
||||
mslog(s, proc, LOG_INFO, "User '%s' authenticated", proc->username);
|
||||
mslog(s, proc, LOG_INFO, "user '%s' of group '%s' authenticated", proc->username, group);
|
||||
} else {
|
||||
mslog(s, proc, LOG_INFO, "User '%s' re-authenticated (using cookie)", proc->username);
|
||||
mslog(s, proc, LOG_INFO, "user '%s' of group '%s' re-authenticated (using cookie)", proc->username, group);
|
||||
}
|
||||
|
||||
ret = send_auth_reply(s, proc, REP_AUTH_OK, lease);
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_ERR, "Could not send reply cmd (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
mslog(s, proc, LOG_ERR, "could not send reply cmd (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
ret = -2;
|
||||
goto lease_cleanup;
|
||||
}
|
||||
@@ -268,10 +272,10 @@ int handle_commands(main_server_st *s, struct proc_st* proc)
|
||||
proc->lease->in_use = 1;
|
||||
ret = 0;
|
||||
} else {
|
||||
mslog(s, proc, LOG_INFO, "Failed authentication attempt for user '%s'", proc->username);
|
||||
mslog(s, proc, LOG_INFO, "failed authentication attempt for user '%s'", proc->username);
|
||||
ret = send_auth_reply( s, proc, REP_AUTH_FAILED, NULL);
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_ERR, "Could not send reply cmd (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
mslog(s, proc, LOG_ERR, "could not send reply cmd (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
ret = -2;
|
||||
goto lease_cleanup;
|
||||
}
|
||||
@@ -288,7 +292,7 @@ lease_cleanup:
|
||||
|
||||
break;
|
||||
default:
|
||||
mslog(s, proc, LOG_ERR, "Unknown CMD 0x%x (pid: %d, peer: %s).", (unsigned)cmd, proc->pid, peer_ip);
|
||||
mslog(s, proc, LOG_ERR, "unknown CMD 0x%x (pid: %d, peer: %s).", (unsigned)cmd, proc->pid, peer_ip);
|
||||
return -2;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ struct proc_st {
|
||||
|
||||
/* The following are set by the worker process (or by a stored cookie) */
|
||||
char username[MAX_USERNAME_SIZE]; /* the owner */
|
||||
char groupname[MAX_GROUPNAME_SIZE]; /* the owner's group */
|
||||
char hostname[MAX_HOSTNAME_SIZE]; /* the requested hostname */
|
||||
uint8_t cookie[COOKIE_SIZE]; /* the cookie associated with the session */
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* DO NOT EDIT THIS FILE (ocserv-args.c)
|
||||
*
|
||||
* It has been AutoGen-ed February 12, 2013 at 01:34:57 PM by AutoGen 5.16
|
||||
* It has been AutoGen-ed February 12, 2013 at 04:34:56 PM by AutoGen 5.16
|
||||
* From the definitions ocserv-args.def
|
||||
* and the template file options
|
||||
*
|
||||
@@ -65,7 +65,7 @@ extern FILE * option_usage_fp;
|
||||
/*
|
||||
* ocserv option static const strings
|
||||
*/
|
||||
static char const ocserv_opt_strs[1505] =
|
||||
static char const ocserv_opt_strs[1501] =
|
||||
/* 0 */ "ocserv\n"
|
||||
"Copyright (C) 2013 Nikos Mavrogiannopoulos, all rights reserved.\n"
|
||||
"This is free software. It is licensed for use, modification and\n"
|
||||
@@ -80,75 +80,75 @@ static char const ocserv_opt_strs[1505] =
|
||||
"details.\n\n"
|
||||
"You should have received a copy of the GNU General Public License, version\n"
|
||||
"2, along with this program. If not, see <http://www.gnu.org/licenses/>.\n\0"
|
||||
/* 803 */ "Do not fork into background.\0"
|
||||
/* 832 */ "FOREGROUND\0"
|
||||
/* 843 */ "foreground\0"
|
||||
/* 854 */ "Enable verbose TLS debugging information.\0"
|
||||
/* 896 */ "TLS_DEBUG\0"
|
||||
/* 906 */ "tls-debug\0"
|
||||
/* 916 */ "Enable verbose network debugging information.\0"
|
||||
/* 962 */ "DEBUG\0"
|
||||
/* 968 */ "debug\0"
|
||||
/* 974 */ "Configuration file for the server.\0"
|
||||
/* 1009 */ "CONFIG\0"
|
||||
/* 1016 */ "config\0"
|
||||
/* 1023 */ "Display extended usage information and exit\0"
|
||||
/* 1067 */ "help\0"
|
||||
/* 1072 */ "Extended usage information passed thru pager\0"
|
||||
/* 1117 */ "more-help\0"
|
||||
/* 1127 */ "OCSERV\0"
|
||||
/* 1134 */ "ocserv - OpenConnect server\n"
|
||||
/* 803 */ "Do not fork into background\0"
|
||||
/* 831 */ "FOREGROUND\0"
|
||||
/* 842 */ "foreground\0"
|
||||
/* 853 */ "Enable verbose TLS debugging information\0"
|
||||
/* 894 */ "TLS_DEBUG\0"
|
||||
/* 904 */ "tls-debug\0"
|
||||
/* 914 */ "Enable verbose network debugging information\0"
|
||||
/* 959 */ "DEBUG\0"
|
||||
/* 965 */ "debug\0"
|
||||
/* 971 */ "Configuration file for the server\0"
|
||||
/* 1005 */ "CONFIG\0"
|
||||
/* 1012 */ "config\0"
|
||||
/* 1019 */ "Display extended usage information and exit\0"
|
||||
/* 1063 */ "help\0"
|
||||
/* 1068 */ "Extended usage information passed thru pager\0"
|
||||
/* 1113 */ "more-help\0"
|
||||
/* 1123 */ "OCSERV\0"
|
||||
/* 1130 */ "ocserv - OpenConnect server\n"
|
||||
"USAGE: %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]...\n\0"
|
||||
/* 1220 */ "nmav@gnutls.org\0"
|
||||
/* 1236 */ "\n\n\0"
|
||||
/* 1239 */ "\n"
|
||||
/* 1216 */ "nmav@gnutls.org\0"
|
||||
/* 1232 */ "\n\n\0"
|
||||
/* 1235 */ "\n"
|
||||
"This program is openconnect VPN server (ocserv), a server compatible with\n"
|
||||
"the openconnect VPN client. It is believed to be compatible with the\n"
|
||||
"protocol used by CISCO's AnyConnect SSL VPN.\n\0"
|
||||
/* 1430 */ "Usage: ocserv [options] -c [config]\n"
|
||||
/* 1426 */ "Usage: ocserv [options] -c [config]\n"
|
||||
"ocserv --help for usage instructions.\n";
|
||||
|
||||
/*
|
||||
* foreground option description:
|
||||
*/
|
||||
#define FOREGROUND_DESC (ocserv_opt_strs+803)
|
||||
#define FOREGROUND_NAME (ocserv_opt_strs+832)
|
||||
#define FOREGROUND_name (ocserv_opt_strs+843)
|
||||
#define FOREGROUND_NAME (ocserv_opt_strs+831)
|
||||
#define FOREGROUND_name (ocserv_opt_strs+842)
|
||||
#define FOREGROUND_FLAGS (OPTST_DISABLED)
|
||||
|
||||
/*
|
||||
* tls-debug option description:
|
||||
*/
|
||||
#define TLS_DEBUG_DESC (ocserv_opt_strs+854)
|
||||
#define TLS_DEBUG_NAME (ocserv_opt_strs+896)
|
||||
#define TLS_DEBUG_name (ocserv_opt_strs+906)
|
||||
#define TLS_DEBUG_DESC (ocserv_opt_strs+853)
|
||||
#define TLS_DEBUG_NAME (ocserv_opt_strs+894)
|
||||
#define TLS_DEBUG_name (ocserv_opt_strs+904)
|
||||
#define TLS_DEBUG_FLAGS (OPTST_DISABLED)
|
||||
|
||||
/*
|
||||
* debug option description:
|
||||
*/
|
||||
#define DEBUG_DESC (ocserv_opt_strs+916)
|
||||
#define DEBUG_NAME (ocserv_opt_strs+962)
|
||||
#define DEBUG_name (ocserv_opt_strs+968)
|
||||
#define DEBUG_DESC (ocserv_opt_strs+914)
|
||||
#define DEBUG_NAME (ocserv_opt_strs+959)
|
||||
#define DEBUG_name (ocserv_opt_strs+965)
|
||||
#define DEBUG_FLAGS (OPTST_DISABLED)
|
||||
|
||||
/*
|
||||
* config option description:
|
||||
*/
|
||||
#define CONFIG_DESC (ocserv_opt_strs+974)
|
||||
#define CONFIG_NAME (ocserv_opt_strs+1009)
|
||||
#define CONFIG_name (ocserv_opt_strs+1016)
|
||||
#define CONFIG_DESC (ocserv_opt_strs+971)
|
||||
#define CONFIG_NAME (ocserv_opt_strs+1005)
|
||||
#define CONFIG_name (ocserv_opt_strs+1012)
|
||||
#define CONFIG_FLAGS (OPTST_DISABLED \
|
||||
| OPTST_SET_ARGTYPE(OPARG_TYPE_FILE))
|
||||
|
||||
/*
|
||||
* Help/More_Help option descriptions:
|
||||
*/
|
||||
#define HELP_DESC (ocserv_opt_strs+1023)
|
||||
#define HELP_name (ocserv_opt_strs+1067)
|
||||
#define HELP_DESC (ocserv_opt_strs+1019)
|
||||
#define HELP_name (ocserv_opt_strs+1063)
|
||||
#ifdef HAVE_WORKING_FORK
|
||||
#define MORE_HELP_DESC (ocserv_opt_strs+1072)
|
||||
#define MORE_HELP_name (ocserv_opt_strs+1117)
|
||||
#define MORE_HELP_DESC (ocserv_opt_strs+1068)
|
||||
#define MORE_HELP_name (ocserv_opt_strs+1113)
|
||||
#define MORE_HELP_FLAGS (OPTST_IMM | OPTST_NO_INIT)
|
||||
#else
|
||||
#define MORE_HELP_DESC NULL
|
||||
@@ -251,13 +251,13 @@ static tOptDesc optDesc[OPTION_CT] = {
|
||||
*
|
||||
* Define the ocserv Option Environment
|
||||
*/
|
||||
#define zPROGNAME (ocserv_opt_strs+1127)
|
||||
#define zUsageTitle (ocserv_opt_strs+1134)
|
||||
#define zPROGNAME (ocserv_opt_strs+1123)
|
||||
#define zUsageTitle (ocserv_opt_strs+1130)
|
||||
#define zRcName NULL
|
||||
#define apzHomeList NULL
|
||||
#define zBugsAddr (ocserv_opt_strs+1220)
|
||||
#define zExplain (ocserv_opt_strs+1236)
|
||||
#define zDetail (ocserv_opt_strs+1239)
|
||||
#define zBugsAddr (ocserv_opt_strs+1216)
|
||||
#define zExplain (ocserv_opt_strs+1232)
|
||||
#define zDetail (ocserv_opt_strs+1235)
|
||||
#define zFullVersion (NULL)
|
||||
/* extracted from optcode.tlib near line 350 */
|
||||
|
||||
@@ -272,7 +272,7 @@ static tOptDesc optDesc[OPTION_CT] = {
|
||||
|
||||
#define ocserv_full_usage (NULL)
|
||||
|
||||
#define ocserv_short_usage (ocserv_opt_strs+1430)
|
||||
#define ocserv_short_usage (ocserv_opt_strs+1426)
|
||||
|
||||
#endif /* not defined __doxygen__ */
|
||||
|
||||
|
||||
@@ -10,11 +10,11 @@ long-opts;
|
||||
no-misuse-usage;
|
||||
short-usage = "Usage: ocserv [options] -c [config]\nocserv --help for usage instructions.\n";
|
||||
explain = "";
|
||||
detail = "This program is openconnect VPN server (ocserv), a server compatible with the
|
||||
openconnect VPN client. It is believed to be compatible with the protocol
|
||||
used by CISCO's AnyConnect SSL VPN.
|
||||
|
||||
";
|
||||
|
||||
detail = "This program is openconnect VPN server (ocserv), a server compatible with the
|
||||
openconnect VPN client. It is believed to be compatible with the protocol
|
||||
used by CISCO's AnyConnect SSL VPN.";
|
||||
|
||||
|
||||
copyright = {
|
||||
@@ -28,20 +28,20 @@ copyright = {
|
||||
flag = {
|
||||
name = foreground;
|
||||
value = f;
|
||||
descrip = "Do not fork into background.";
|
||||
descrip = "Do not fork into background";
|
||||
doc = "";
|
||||
};
|
||||
|
||||
flag = {
|
||||
name = tls-debug;
|
||||
descrip = "Enable verbose TLS debugging information.";
|
||||
descrip = "Enable verbose TLS debugging information";
|
||||
doc = "";
|
||||
};
|
||||
|
||||
flag = {
|
||||
name = debug;
|
||||
value = d;
|
||||
descrip = "Enable verbose network debugging information.";
|
||||
descrip = "Enable verbose network debugging information";
|
||||
doc = "";
|
||||
};
|
||||
|
||||
@@ -50,34 +50,19 @@ flag = {
|
||||
value = c;
|
||||
arg-type = file;
|
||||
file-exists = yes;
|
||||
descrip = "Configuration file for the server.";
|
||||
descrip = "Configuration file for the server";
|
||||
doc = "";
|
||||
};
|
||||
|
||||
help-value = h;
|
||||
|
||||
doc-section = {
|
||||
ds-type = 'FEATURES';
|
||||
ds-format = 'texi';
|
||||
ds-text = <<-_EOT_
|
||||
@subheading Features of the server
|
||||
@itemize
|
||||
@item Supports both TCP and UDP VPN tunnels using TLS and DTLS.
|
||||
@item Authentication using PAM (username-password) or certificates
|
||||
@item Privilege separation between the main process which performs TUN allocation and authentication, with the worker processes which handles messages from the client.
|
||||
@item Registers VPN leases to UTMP and WTMP files.
|
||||
@item Persistent storage of cookies, to allow a seamless server restart.
|
||||
@end itemize
|
||||
_EOT_;
|
||||
};
|
||||
|
||||
|
||||
doc-section = {
|
||||
ds-type = 'FILES';
|
||||
ds-format = 'texi';
|
||||
ds-text = <<-_EOT_
|
||||
@subheading ocserv's configuration file format
|
||||
|
||||
By default, if no other file is specified, ocserv looks for its configuration file at @file{/etc/ocserv.conf}.
|
||||
An example configuration file follows.
|
||||
|
||||
@example
|
||||
@@ -125,6 +110,12 @@ server-key = /path/to/key.pem
|
||||
# CN = 2.5.4.3, UID = 0.9.2342.19200300.100.1.1
|
||||
#cert-user-oid = 0.9.2342.19200300.100.1.1
|
||||
|
||||
# The object identifier that will be used to read the user group in the client
|
||||
# certificate. The object identifier should be part of the certificate's DN
|
||||
# Useful OIDs are:
|
||||
# OU (organizational unit) = 2.5.4.11
|
||||
#cert-group-oid = 2.5.4.11
|
||||
|
||||
# A revocation list of ca-cert is set
|
||||
#crl = /path/to/crl.pem
|
||||
|
||||
@@ -149,7 +140,7 @@ cookie-validity = 14400
|
||||
#cookie-db = /var/tmp/cookies.db
|
||||
|
||||
# Script to call when a client connects and obtains an IP
|
||||
# Parameters: username hostname device IP-REAL IP-LOCAL IP-REMOTE
|
||||
# Parameters: username groupname hostname device IP-REAL IP-LOCAL IP-REMOTE
|
||||
# hostname is the hostname selected by the client
|
||||
# IP-REAL is the remote IP of the client,
|
||||
# IP-LOCAL is the local IP in the P-t-P connection and IP-REMOTE
|
||||
@@ -201,7 +192,6 @@ ocserv will take advantage of it to password authenticate its users.
|
||||
It can be used in conjunction with certificate authentication.
|
||||
|
||||
@subheading Certificate authentication
|
||||
|
||||
In order to support certificate authentication you will need in addition to
|
||||
the server certificate and key for TLS, a certificate authority (CA) to sign
|
||||
certificates for the clients. That authority should also provide a CRL to
|
||||
@@ -262,3 +252,30 @@ the HUP signal.
|
||||
|
||||
_EOT_;
|
||||
};
|
||||
|
||||
doc-section = {
|
||||
ds-type = 'IMPLEMENTATION NOTES';
|
||||
ds-format = 'texi';
|
||||
ds-text = <<-_EOT_
|
||||
Note that while this server utilizes privilege separation for password
|
||||
authentication, this does not occur for TLS and client certificate authentication.
|
||||
This was done to take advantage of multi-core systems by distributing the
|
||||
expensive TLS calculations to the workers.
|
||||
_EOT_;
|
||||
};
|
||||
|
||||
doc-section = {
|
||||
ds-type = 'COMPATIBILITY';
|
||||
ds-format = 'texi';
|
||||
ds-text = <<-_EOT_
|
||||
@subheading Features of the server
|
||||
@itemize
|
||||
@item Supports both TCP and UDP VPN tunnels using TLS and DTLS.
|
||||
@item Support for the server key being stored in TPM, a hardware security module (HSM), or smart card.
|
||||
@item Authentication using PAM (username-password) or certificates
|
||||
@item Privilege separation between the main process which performs TUN allocation and authentication, with the worker processes which handles messages from the client.
|
||||
@item Registers VPN leases to UTMP and WTMP files.
|
||||
@item Persistent storage of cookies, to allow a seamless server restart.
|
||||
@end itemize
|
||||
_EOT_;
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* DO NOT EDIT THIS FILE (ocserv-args.h)
|
||||
*
|
||||
* It has been AutoGen-ed February 12, 2013 at 01:34:57 PM by AutoGen 5.16
|
||||
* It has been AutoGen-ed February 12, 2013 at 04:34:56 PM by AutoGen 5.16
|
||||
* From the definitions ocserv-args.def
|
||||
* and the template file options
|
||||
*
|
||||
|
||||
21
src/pam.c
21
src/pam.c
@@ -6,6 +6,9 @@
|
||||
#ifdef HAVE_PAM
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#define APP_NAME PACKAGE
|
||||
|
||||
@@ -44,12 +47,13 @@ struct pam_response *replies;
|
||||
|
||||
/* Returns 0 if the user is successfully authenticated
|
||||
*/
|
||||
int pam_auth_user(const char* user, const char* pass)
|
||||
int pam_auth_user(const char* user, const char* pass, char *groupname, int groupname_size)
|
||||
{
|
||||
pam_handle_t * ph;
|
||||
int ret, pret;
|
||||
struct local_st local;
|
||||
const struct pam_conv dc = { dummy_conv, &local };
|
||||
struct passwd * pwd;
|
||||
|
||||
local.username = user;
|
||||
local.password = pass;
|
||||
@@ -66,6 +70,21 @@ const struct pam_conv dc = { dummy_conv, &local };
|
||||
ret = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pret = pam_acct_mgmt(ph, PAM_SILENT|PAM_DISALLOW_NULL_AUTHTOK);
|
||||
if (pret != PAM_SUCCESS) {
|
||||
syslog(LOG_AUTH, "Error in PAM account management: %s", pam_strerror(ph, pret));
|
||||
ret = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
groupname[0] = 0;
|
||||
pwd = getpwnam(user);
|
||||
if (pwd != NULL) {
|
||||
struct group* grp = getgrgid(pwd->pw_gid);
|
||||
if (grp != NULL)
|
||||
snprintf(groupname, groupname_size, "%s", grp->gr_name);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
fail:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#ifndef PAM_H
|
||||
#define PAM_H
|
||||
|
||||
int pam_auth_user(const char* user, const char* pass);
|
||||
int pam_auth_user(const char* user, const char* pass, char *groupname, int groupname_size);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -60,6 +60,7 @@ struct cfg_st {
|
||||
char *ca;
|
||||
char *crl;
|
||||
char *cert_user_oid; /* The OID that will be used to extract the username */
|
||||
char *cert_group_oid; /* The OID that will be used to extract the groupname */
|
||||
unsigned int auth_types; /* or'ed sequence of AUTH_TYPE */
|
||||
gnutls_certificate_request_t cert_req;
|
||||
char *priorities;
|
||||
@@ -98,6 +99,7 @@ struct main_server_st;
|
||||
#define MAX_PASSWORD_SIZE 64
|
||||
#define TLS_MASTER_SIZE 48
|
||||
#define MAX_HOSTNAME_SIZE MAX_USERNAME_SIZE
|
||||
#define MAX_GROUPNAME_SIZE MAX_USERNAME_SIZE
|
||||
#define COOKIE_SIZE 32
|
||||
#define MAX_SESSION_DATA_SIZE (4*1024)
|
||||
|
||||
|
||||
@@ -95,8 +95,9 @@ int ret;
|
||||
}
|
||||
|
||||
static
|
||||
int get_cert_username(worker_st *ws, const gnutls_datum_t* raw,
|
||||
char* username, size_t username_size)
|
||||
int get_cert_names(worker_st *ws, const gnutls_datum_t* raw,
|
||||
char* username, size_t username_size,
|
||||
char* groupname, size_t groupname_size)
|
||||
{
|
||||
gnutls_x509_crt_t crt;
|
||||
int ret;
|
||||
@@ -120,9 +121,20 @@ int ret;
|
||||
ret = gnutls_x509_crt_get_dn (crt, username, &username_size);
|
||||
}
|
||||
if (ret < 0) {
|
||||
oclog(ws, LOG_ERR, "certificate error in DN: %s", gnutls_strerror(ret));
|
||||
oclog(ws, LOG_ERR, "cannot obtain user from certificate DN: %s", gnutls_strerror(ret));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (ws->config->cert_group_oid) {
|
||||
ret = gnutls_x509_crt_get_dn_by_oid (crt, ws->config->cert_group_oid,
|
||||
0, 0, groupname, &groupname_size);
|
||||
if (ret < 0) {
|
||||
oclog(ws, LOG_ERR, "cannot obtain group from certificate DN: %s", gnutls_strerror(ret));
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
groupname[0] = 0;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
@@ -246,7 +258,8 @@ static int recv_auth_reply(worker_st *ws)
|
||||
|
||||
/* grabs the username from the session certificate */
|
||||
static
|
||||
int get_cert_info(worker_st *ws, char* user, unsigned user_size)
|
||||
int get_cert_info(worker_st *ws, char* user, unsigned user_size,
|
||||
char* group, unsigned group_size)
|
||||
{
|
||||
const gnutls_datum_t * cert;
|
||||
unsigned int ncerts;
|
||||
@@ -260,7 +273,7 @@ int ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = get_cert_username(ws, cert, user, user_size);
|
||||
ret = get_cert_names(ws, cert, user, user_size, group, group_size);
|
||||
if (ret < 0) {
|
||||
oclog(ws, LOG_ERR, "Cannot get username (%s) from certificate", ws->config->cert_user_oid);
|
||||
return -1;
|
||||
@@ -278,7 +291,8 @@ static int auth_user(worker_st *ws, struct cmd_auth_req_st* areq)
|
||||
int ret;
|
||||
|
||||
if (ws->config->auth_types & AUTH_TYPE_CERTIFICATE) {
|
||||
ret = get_cert_info(ws, areq->cert_user, sizeof(areq->cert_user));
|
||||
ret = get_cert_info(ws, areq->cert_user, sizeof(areq->cert_user),
|
||||
areq->cert_group, sizeof(areq->cert_group));
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
@@ -308,7 +322,8 @@ struct cmd_auth_cookie_req_st areq;
|
||||
return -1;
|
||||
|
||||
if (ws->config->auth_types & AUTH_TYPE_CERTIFICATE) {
|
||||
ret = get_cert_info(ws, areq.cert_user, sizeof(areq.cert_user));
|
||||
ret = get_cert_info(ws, areq.cert_user, sizeof(areq.cert_user),
|
||||
areq.cert_group, sizeof(areq.cert_group));
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
@@ -321,7 +336,7 @@ struct cmd_auth_cookie_req_st areq;
|
||||
ret = send_auth_cookie_req(ws->cmd_fd, &areq);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
||||
return recv_auth_reply(ws);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user