-/* $OpenBSD: config.c,v 1.29 2015/01/13 09:21:15 reyk Exp $ */
+/* $OpenBSD: config.c,v 1.30 2015/01/19 19:37:50 reyk Exp $ */
/*
* Copyright (c) 2011 - 2015 Reyk Floeter <reyk@openbsd.org>
int config_getserver_config(struct httpd *, struct server *,
struct imsg *);
+int config_getserver_auth(struct httpd *, struct server_config *);
int
config_init(struct httpd *env)
env->sc_prefork_server = SERVER_NUMPROC;
ps->ps_what[PROC_PARENT] = CONFIG_ALL;
- ps->ps_what[PROC_SERVER] = CONFIG_SERVERS|CONFIG_MEDIA;
+ ps->ps_what[PROC_SERVER] =
+ CONFIG_SERVERS|CONFIG_MEDIA|CONFIG_AUTH;
ps->ps_what[PROC_LOGGER] = CONFIG_SERVERS;
}
RB_INIT(env->sc_mediatypes);
}
+ if (what & CONFIG_AUTH) {
+ if ((env->sc_auth =
+ calloc(1, sizeof(*env->sc_auth))) == NULL)
+ return (-1);
+ TAILQ_INIT(env->sc_auth);
+ }
+
return (0);
}
{
struct privsep *ps = env->sc_ps;
struct server *srv;
+ struct auth *auth;
u_int what;
what = ps->ps_what[privsep_process] & reset;
if (what & CONFIG_MEDIA && env->sc_mediatypes != NULL)
media_purge(env->sc_mediatypes);
+
+ if (what & CONFIG_AUTH && env->sc_auth != NULL) {
+ while ((auth = TAILQ_FIRST(env->sc_auth)) != NULL) {
+ auth_free(env->sc_auth, auth);
+ free(auth);
+ }
+ }
}
int
return (0);
}
+int
+config_getserver_auth(struct httpd *env, struct server_config *srv_conf)
+{
+ struct privsep *ps = env->sc_ps;
+
+ if ((ps->ps_what[privsep_process] & CONFIG_AUTH) == 0 ||
+ (srv_conf->flags & SRVFLAG_AUTH) == 0)
+ return (0);
+
+ if ((srv_conf->auth = auth_byid(env->sc_auth,
+ srv_conf->auth_id)) == NULL)
+ return (-1);
+
+ return (0);
+}
+
int
config_getserver_config(struct httpd *env, struct server *srv,
struct imsg *imsg)
if (parent == NULL)
parent = &srv->srv_conf;
+ if (config_getserver_auth(env, srv_conf) != 0)
+ return (-1);
+
if (srv_conf->flags & SRVFLAG_LOCATION) {
/* Inherit configuration from the parent */
f = SRVFLAG_INDEX|SRVFLAG_NO_INDEX;
if ((srv_conf->flags & f) == 0)
srv_conf->flags |= parent->flags & f;
+ f = SRVFLAG_AUTH|SRVFLAG_NO_AUTH;
+ if ((srv_conf->flags & f) == 0) {
+ srv_conf->flags |= parent->flags & f;
+ srv_conf->auth = parent->auth;
+ srv_conf->auth_id = parent->auth_id;
+ (void)strlcpy(srv_conf->auth_realm,
+ parent->auth_realm,
+ sizeof(srv_conf->auth_realm));
+ }
+
f = SRVFLAG_TLS;
srv_conf->flags |= parent->flags & f;
fatalx("invalid location");
/* Otherwise create a new server */
- if ((srv = calloc(1, sizeof(*srv))) == NULL) {
- close(imsg->fd);
- return (-1);
- }
+ if ((srv = calloc(1, sizeof(*srv))) == NULL)
+ goto fail;
memcpy(&srv->srv_conf, &srv_conf, sizeof(srv->srv_conf));
srv->srv_s = imsg->fd;
+ if (config_getserver_auth(env, &srv->srv_conf) != 0)
+ goto fail;
+
SPLAY_INIT(&srv->srv_clients);
TAILQ_INIT(&srv->srv_hosts);
return (0);
fail:
+ if (imsg->fd != -1)
+ close(imsg->fd);
if (srv != NULL) {
free(srv->srv_conf.tls_cert);
free(srv->srv_conf.tls_key);
return (0);
}
+
+int
+config_setauth(struct httpd *env, struct auth *auth)
+{
+ struct privsep *ps = env->sc_ps;
+ int id;
+ u_int what;
+
+ for (id = 0; id < PROC_MAX; id++) {
+ what = ps->ps_what[id];
+
+ if ((what & CONFIG_AUTH) == 0 || id == privsep_process)
+ continue;
+
+ DPRINTF("%s: sending auth \"%s[%u]\" to %s", __func__,
+ auth->auth_htpasswd, auth->auth_id, ps->ps_title[id]);
+
+ proc_compose_imsg(ps, id, -1, IMSG_CFG_AUTH, -1,
+ auth, sizeof(*auth));
+ }
+
+ return (0);
+}
+
+int
+config_getauth(struct httpd *env, struct imsg *imsg)
+{
+#ifdef DEBUG
+ struct privsep *ps = env->sc_ps;
+#endif
+ struct auth auth;
+ u_int8_t *p = imsg->data;
+
+ IMSG_SIZE_CHECK(imsg, &auth);
+ memcpy(&auth, p, sizeof(auth));
+
+ if (auth_add(env->sc_auth, &auth) == NULL) {
+ log_debug("%s: failed to add auth \"%s[%u]\"",
+ __func__, auth.auth_htpasswd, auth.auth_id);
+ return (-1);
+ }
+
+ DPRINTF("%s: %s %d received auth \"%s[%u]\"", __func__,
+ ps->ps_title[privsep_process], ps->ps_instance,
+ auth.auth_htpasswd, auth.auth_id);
+
+ return (0);
+}
-/* $OpenBSD: httpd.c,v 1.29 2015/01/16 06:40:17 deraadt Exp $ */
+/* $OpenBSD: httpd.c,v 1.30 2015/01/19 19:37:50 reyk Exp $ */
/*
* Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
int ret = -1;
struct server *srv;
struct media_type *media;
+ struct auth *auth;
RB_FOREACH(media, mediatypes, env->sc_mediatypes) {
if (config_setmedia(env, media) == -1)
fatal("send media");
}
+ TAILQ_FOREACH(auth, env->sc_auth, auth_entry) {
+ if (config_setauth(env, auth) == -1)
+ fatal("send auth");
+ }
+
/* First send the servers... */
TAILQ_FOREACH(srv, env->sc_servers, srv_entry) {
if (srv->srv_conf.flags & SRVFLAG_LOCATION)
}
RB_GENERATE(mediatypes, media_type, media_entry, media_cmp);
+
+struct auth *
+auth_add(struct serverauth *serverauth, struct auth *auth)
+{
+ struct auth *entry;
+
+ TAILQ_FOREACH(entry, serverauth, auth_entry) {
+ if (strcmp(entry->auth_htpasswd, auth->auth_htpasswd) == 0)
+ return (entry);
+ }
+
+ if ((entry = calloc(1, sizeof(*entry))) == NULL)
+ return (NULL);
+
+ memcpy(entry, auth, sizeof(*entry));
+
+ TAILQ_INSERT_TAIL(serverauth, entry, auth_entry);
+
+ return (entry);
+}
+
+struct auth *
+auth_byid(struct serverauth *serverauth, u_int32_t id)
+{
+ struct auth *auth;
+
+ TAILQ_FOREACH(auth, serverauth, auth_entry) {
+ if (auth->auth_id == id)
+ return (auth);
+ }
+
+ return (NULL);
+}
+
+void
+auth_free(struct serverauth *serverauth, struct auth *auth)
+{
+ TAILQ_REMOVE(serverauth, auth, auth_entry);
+}
-.\" $OpenBSD: httpd.conf.5,v 1.46 2015/01/18 18:39:46 florian Exp $
+.\" $OpenBSD: httpd.conf.5,v 1.47 2015/01/19 19:37:50 reyk Exp $
.\"
.\" Copyright (c) 2014, 2015 Reyk Floeter <reyk@openbsd.org>
.\"
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: January 18 2015 $
+.Dd $Mdocdate: January 19 2015 $
.Dt HTTPD.CONF 5
.Os
.Sh NAME
Specify an additional alias
.Ar name
for this server.
-.It Ic authenticate Oo Ar realm Oc Ic with Pa htpasswd
+.It Oo Ic no Oc Ic authenticate Oo Ar realm Oc Ic with Pa htpasswd
Authenticate a remote user for
.Ar realm
by checking the credentials against the user authentication file
The file name is relative to the
.Ic chroot
and must be readable by the www user.
+Use the
+.Ic no authenticate
+directive to disable authentication in a location.
.It Ic connection Ar option
Set the specified options and limits for HTTP connections.
Valid options are:
-/* $OpenBSD: httpd.h,v 1.69 2015/01/18 14:01:17 florian Exp $ */
+/* $OpenBSD: httpd.h,v 1.70 2015/01/19 19:37:50 reyk Exp $ */
/*
* Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org>
#define CONFIG_RELOAD 0x00
#define CONFIG_MEDIA 0x01
#define CONFIG_SERVERS 0x02
+#define CONFIG_AUTH 0x04
#define CONFIG_ALL 0xff
#define FCGI_CONTENT_SIZE 65535
IMSG_CTL_REOPEN,
IMSG_CFG_SERVER,
IMSG_CFG_MEDIA,
+ IMSG_CFG_AUTH,
IMSG_CFG_DONE,
IMSG_LOG_ACCESS,
IMSG_LOG_ERROR,
#define SRVFLAG_TLS 0x00002000
#define SRVFLAG_ACCESS_LOG 0x00004000
#define SRVFLAG_ERROR_LOG 0x00008000
-#define SRVFLAG_AUTH_BASIC 0x00010000
+#define SRVFLAG_AUTH 0x00010000
+#define SRVFLAG_NO_AUTH 0x00020000
#define SRVFLAG_BITS \
"\10\01INDEX\02NO_INDEX\03AUTO_INDEX\04NO_AUTO_INDEX" \
"\05ROOT\06LOCATION\07FCGI\10NO_FCGI\11LOG\12NO_LOG\13SOCKET" \
"\14SYSLOG\15NO_SYSLOG\16TLS\17ACCESS_LOG\20ERROR_LOG" \
- "\21AUTH_BASIC"
+ "\21AUTH\22NO_AUTH"
#define TCPFLAG_NODELAY 0x01
#define TCPFLAG_NNODELAY 0x02
};
TAILQ_HEAD(log_files, log_file) log_files;
+struct auth {
+ char auth_htpasswd[PATH_MAX];
+ u_int32_t auth_id;
+ TAILQ_ENTRY(auth) auth_entry;
+};
+TAILQ_HEAD(serverauth, auth);
+
struct server_config {
u_int32_t id;
char name[HOST_NAME_MAX+1];
char socket[PATH_MAX];
char accesslog[NAME_MAX];
char errorlog[NAME_MAX];
- char auth_realm[NAME_MAX];
- char auth_htpasswd[PATH_MAX];
in_port_t port;
struct sockaddr_storage ss;
struct log_file *logaccess;
struct log_file *logerror;
+ char auth_realm[NAME_MAX];
+ u_int32_t auth_id;
+ struct auth *auth;
+
TAILQ_ENTRY(server_config) entry;
};
TAILQ_HEAD(serverhosts, server_config);
struct serverlist *sc_servers;
struct mediatypes *sc_mediatypes;
+ struct serverauth *sc_auth;
struct privsep *sc_ps;
int sc_reload;
int media_cmp(struct media_type *, struct media_type *);
RB_PROTOTYPE(kvtree, kv, kv_node, kv_cmp);
RB_PROTOTYPE(mediatypes, media_type, media_entry, media_cmp);
+struct auth *auth_add(struct serverauth *, struct auth *);
+struct auth *auth_byid(struct serverauth *, u_int32_t);
+void auth_free(struct serverauth *, struct auth *);
/* log.c */
void log_init(int);
int config_getserver(struct httpd *, struct imsg *);
int config_setmedia(struct httpd *, struct media_type *);
int config_getmedia(struct httpd *, struct imsg *);
+int config_setauth(struct httpd *, struct auth *);
+int config_getauth(struct httpd *, struct imsg *);
/* logger.c */
pid_t logger(struct privsep *, struct privsep_proc *);
-/* $OpenBSD: parse.y,v 1.55 2015/01/18 14:01:17 florian Exp $ */
+/* $OpenBSD: parse.y,v 1.56 2015/01/19 19:37:50 reyk Exp $ */
/*
* Copyright (c) 2007 - 2015 Reyk Floeter <reyk@openbsd.org>
static int errors = 0;
static int loadcfg = 0;
uint32_t last_server_id = 0;
+uint32_t last_auth_id = 0;
static struct server *srv = NULL, *parentsrv = NULL;
static struct server_config *srv_conf = NULL;
char *string;
struct timeval tv;
struct portrange port;
+ struct auth auth;
struct {
struct sockaddr_storage ss;
char name[HOST_NAME_MAX+1];
%type <v.number> opttls
%type <v.tv> timeout
%type <v.string> numberstring
+%type <v.auth> authopts
%%
}
;
-authenticate : AUTHENTICATE STRING WITH STRING {
- if (strlcpy(srv->srv_conf.auth_realm, $2,
+authenticate : NO AUTHENTICATE {
+ srv->srv_conf.flags |= SRVFLAG_NO_AUTH;
+ }
+ | AUTHENTICATE authopts {
+ struct auth *auth;
+
+ if ((auth = auth_add(conf->sc_auth, &$2)) == NULL) {
+ yyerror("failed to add auth");
+ YYERROR;
+ }
+
+ if (auth->auth_id == 0) {
+ /* New htpasswd, get new Id */
+ auth->auth_id = ++last_auth_id;
+ if (last_auth_id == INT_MAX) {
+ yyerror("too many auth ids defined");
+ auth_free(conf->sc_auth, auth);
+ YYERROR;
+ }
+ }
+
+ srv->srv_conf.auth_id = auth->auth_id;
+ srv->srv_conf.flags |= SRVFLAG_AUTH;
+ }
+ ;
+
+authopts : STRING WITH STRING {
+ if (strlcpy(srv->srv_conf.auth_realm, $1,
sizeof(srv->srv_conf.auth_realm)) >=
sizeof(srv->srv_conf.auth_realm)) {
yyerror("basic auth realm name too long");
- free($2);
+ free($1);
YYERROR;
}
- free($2);
- if (strlcpy(srv->srv_conf.auth_htpasswd, $4,
- sizeof(srv->srv_conf.auth_htpasswd)) >=
- sizeof(srv->srv_conf.auth_htpasswd)) {
+ free($1);
+ if (strlcpy($$.auth_htpasswd, $3,
+ sizeof($$.auth_htpasswd)) >=
+ sizeof($$.auth_htpasswd)) {
yyerror("password file name too long");
- free($4);
+ free($3);
YYERROR;
}
- free($4);
- srv->srv_conf.flags |= SRVFLAG_AUTH_BASIC;
+ free($3);
+
}
- | AUTHENTICATE WITH STRING {
- if (strlcpy(srv->srv_conf.auth_htpasswd, $3,
- sizeof(srv->srv_conf.auth_htpasswd)) >=
- sizeof(srv->srv_conf.auth_htpasswd)) {
+ | WITH STRING {
+ if (strlcpy($$.auth_htpasswd, $2,
+ sizeof($$.auth_htpasswd)) >=
+ sizeof($$.auth_htpasswd)) {
yyerror("password file name too long");
- free($3);
+ free($2);
YYERROR;
}
- free($3);
- srv->srv_conf.flags |= SRVFLAG_AUTH_BASIC;
+ free($2);
};
directory : DIRECTORY dirflags
loadcfg = 1;
errors = 0;
last_server_id = 0;
+ last_auth_id = 0;
srv = NULL;
-/* $OpenBSD: server.c,v 1.52 2015/01/16 06:40:17 deraadt Exp $ */
+/* $OpenBSD: server.c,v 1.53 2015/01/19 19:37:50 reyk Exp $ */
/*
* Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org>
{
srv_conf->tls_cert_file = srv_conf->tls_cert =
srv_conf->tls_key_file = srv_conf->tls_key = NULL;
+ srv_conf->auth = NULL;
}
struct server *
case IMSG_CFG_MEDIA:
config_getmedia(env, imsg);
break;
+ case IMSG_CFG_AUTH:
+ config_getauth(env, imsg);
+ break;
case IMSG_CFG_SERVER:
config_getserver(env, imsg);
break;
-/* $OpenBSD: server_fcgi.c,v 1.47 2015/01/18 14:01:17 florian Exp $ */
+/* $OpenBSD: server_fcgi.c,v 1.48 2015/01/19 19:37:50 reyk Exp $ */
/*
* Copyright (c) 2014 Florian Obser <florian@openbsd.org>
goto fail;
}
- if (srv_conf->flags & SRVFLAG_AUTH_BASIC) {
+ if (srv_conf->flags & SRVFLAG_AUTH) {
if (fcgi_add_param(¶m, "REMOTE_USER",
clt->clt_fcgi_remote_user, clt) == -1) {
errstr = "failed to encode param";
-/* $OpenBSD: server_http.c,v 1.65 2015/01/18 14:01:17 florian Exp $ */
+/* $OpenBSD: server_http.c,v 1.66 2015/01/19 19:37:50 reyk Exp $ */
/*
* Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org>
{
FILE *fp = NULL;
struct http_descriptor *desc = clt->clt_descreq;
+ struct auth *auth = srv_conf->auth;
struct kv *ba, key;
size_t linesize = 0;
ssize_t linelen;
if (clt_pass == NULL)
goto done;
- if ((fp = fopen(srv_conf->auth_htpasswd, "r")) == NULL)
+ if ((fp = fopen(auth->auth_htpasswd, "r")) == NULL)
goto done;
while ((linelen = getline(&line, &linesize, fp)) != -1) {
/* Now search for the location */
srv_conf = server_getlocation(clt, desc->http_path);
- if (srv_conf->flags & SRVFLAG_AUTH_BASIC &&
+ if (srv_conf->flags & SRVFLAG_AUTH &&
server_http_authenticate(srv_conf, clt) == -1) {
server_abort_http(clt, 401, srv_conf->auth_realm);
return (-1);