diff --git a/doc/sample.config b/doc/sample.config index 7ad849fc..d825abe2 100644 --- a/doc/sample.config +++ b/doc/sample.config @@ -2,9 +2,13 @@ # all should succeed. # Options: certificate, pam. #auth = "certificate" -auth = "plain[./sample.passwd]" +#auth = "plain[./sample.passwd]" #auth = "pam" +# The gid-min option is used by auto-select-group option, in order to +# select the minimum group ID. +#auth = "pam[gid-min=1000]" + # The plain option requires specifying a password file which contains # entries of the following format. # "username:groupname:encoded-password" @@ -281,12 +285,12 @@ route = 192.168.5.0/255.255.255.0 # The name of the group that if selected it would allow to use # the assigned by default group. -#default-select-group = DEFAULT +default-select-group = DEFAULT # Instead of specifying manually all the allowed groups, you may instruct # ocserv to scan all available groups and include the full list. That # option is only functional on plain authentication. -#auto-select-group = true +auto-select-group = true # The system command to use to setup a route. %{R} will be replaced with the # route/mask and %{D} with the (tun) device. diff --git a/src/auth/pam.c b/src/auth/pam.c index d77794df..a1c3f0b3 100644 --- a/src/auth/pam.c +++ b/src/auth/pam.c @@ -347,6 +347,43 @@ struct pam_ctx_st * pctx = ctx; talloc_free(pctx); } +static void pam_group_list(void *pool, void *_additional, char ***groupname, unsigned *groupname_size) +{ + struct group *grp; + gid_t min = 0; + char *additional = _additional; + + if (additional != NULL) { + if (strstr(additional, "gid-min=") != NULL) { + additional += 8; + min = atoi(additional); + } else { + syslog(LOG_INFO, "unknown PAM auth string '%s'", additional); + } + } + + setgrent(); + + *groupname_size = 0; + *groupname = talloc_size(pool, sizeof(char*)*MAX_GROUPS); + if (*groupname == NULL) { + goto exit; + } + + while((grp = getgrent()) != NULL && (*groupname_size) < MAX_GROUPS) { + if (grp->gr_gid >= min) { + (*groupname)[(*groupname_size)] = talloc_strdup(*groupname, grp->gr_name); + if ((*groupname)[(*groupname_size)] == NULL) + break; + (*groupname_size)++; + } + } + + exit: + endgrent(); + return; +} + const struct auth_mod_st pam_auth_funcs = { .type = AUTH_TYPE_PAM | AUTH_TYPE_USERNAME_PASS, .auth_init = pam_auth_init, @@ -355,7 +392,7 @@ const struct auth_mod_st pam_auth_funcs = { .auth_pass = pam_auth_pass, .auth_group = pam_auth_group, .auth_user = pam_auth_user, - .group_list = NULL + .group_list = pam_group_list }; #endif diff --git a/src/config.c b/src/config.c index cde5168e..e04a9bf1 100644 --- a/src/config.c +++ b/src/config.c @@ -356,7 +356,8 @@ unsigned force_cert_auth; READ_MULTI_LINE("auth", auth, auth_size); for (j=0;jauth_additional = get_brackets_string(config, auth[j]+3); if ((config->auth_types & AUTH_TYPE_USERNAME_PASS) != 0) { fprintf(stderr, "You cannot mix multiple username/password authentication methods\n"); exit(1); @@ -374,8 +375,8 @@ unsigned force_cert_auth; exit(1); } - config->plain_passwd = get_brackets_string(config, auth[j]+5); - if (config->plain_passwd == NULL) { + config->auth_additional = get_brackets_string(config, auth[j]+5); + if (config->auth_additional == NULL) { fprintf(stderr, "Format error in %s\n", auth[j]); exit(1); } @@ -563,7 +564,7 @@ unsigned force_cert_auth; READ_STRING("default-select-group", config->default_select_group); READ_TF("auto-select-group", auto_select_group, 0); if (auto_select_group != 0 && amod != NULL && amod->group_list != NULL) { - amod->group_list(config, config->plain_passwd, &config->group_list, &config->group_list_size); + amod->group_list(config, config->auth_additional, &config->group_list, &config->group_list_size); } else { READ_MULTI_BRACKET_LINE("select-group", config->group_list, @@ -639,9 +640,9 @@ static void check_cfg(struct cfg_st *config) config->cert_req = GNUTLS_CERT_REQUEST; } - if (config->plain_passwd != NULL) { - if (access(config->plain_passwd, R_OK) != 0) { - fprintf(stderr, "cannot access password file '%s'\n", config->plain_passwd); + if (config->auth_additional != NULL && (config->auth_types & AUTH_TYPE_PLAIN) == AUTH_TYPE_PLAIN) { + if (access(config->auth_additional, R_OK) != 0) { + fprintf(stderr, "cannot access password file '%s'\n", config->auth_additional); exit(1); } } @@ -730,7 +731,7 @@ unsigned i; DEL(config->per_group_dir); DEL(config->socket_file_prefix); DEL(config->default_domain); - DEL(config->plain_passwd); + DEL(config->auth_additional); DEL(config->ocsp_response); DEL(config->banner); DEL(config->dh_params_file); diff --git a/src/ocserv-args.def b/src/ocserv-args.def index 8b61457d..f3fc3802 100644 --- a/src/ocserv-args.def +++ b/src/ocserv-args.def @@ -75,11 +75,15 @@ An example configuration file follows. # that case all should succeed. To enable multiple methods use # multiple auth directives. Available options: certificate, plain, pam. #auth = "certificate" -auth = "pam" +#auth = "pam" + +# The gid-min option is used by auto-select-group option, in order to +# select the minimum group ID. +#auth = "pam[gid-min=1000]" # The plain option requires specifying a password file which contains # entries of the following format. -# "username:groupname:encoded-password" +# "username:groupname1,groupname2:encoded-password" # One entry must be listed per line, and 'ocpasswd' can be used # to generate password entries. #auth = "plain[/etc/ocserv/ocpasswd]" @@ -358,8 +362,7 @@ route = 192.168.5.0/255.255.255.0 #default-select-group = DEFAULT # Instead of specifying manually all the allowed groups, you may instruct -# ocserv to scan all available groups and include the full list. That -# option is only functional on plain authentication. +# ocserv to scan all available groups and include the full list. #auto-select-group = true # Configuration files that will be applied per user connection or diff --git a/src/sec-mod-auth.c b/src/sec-mod-auth.c index 204d86b5..53387d60 100644 --- a/src/sec-mod-auth.c +++ b/src/sec-mod-auth.c @@ -376,7 +376,7 @@ int handle_sec_auth_init(sec_mod_st * sec, const SecAuthInitMsg * req) /* req->username is non-null at this point */ ret = module->auth_init(&e->auth_ctx, e, req->user_name, req->ip, - sec->config->plain_passwd); + sec->config->auth_additional); if (ret < 0) { return ret; } diff --git a/src/vpn.h b/src/vpn.h index bb28c9e5..8c6b36c6 100644 --- a/src/vpn.h +++ b/src/vpn.h @@ -191,7 +191,7 @@ struct cfg_st { 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 */ - char *plain_passwd; /* the password file in plain auth mode */ + char *auth_additional; /* the additional string specified in the auth methode */ gnutls_certificate_request_t cert_req; char *priorities; char *chroot_dir; /* where the xml files are served from */