aboutsummaryrefslogtreecommitdiff
path: root/dico
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2008-07-24 12:12:33 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2008-07-24 12:12:33 +0300
commiteb7f98862dbe400f801de9f47f379fbed428f0f3 (patch)
tree745737c82c70bf13e80f92c384e12c68ee6079e2 /dico
parent38e0c8ac1be999f5303b7f7cc690f9a2a76f0414 (diff)
downloaddico-eb7f98862dbe400f801de9f47f379fbed428f0f3.tar.gz
dico-eb7f98862dbe400f801de9f47f379fbed428f0f3.tar.bz2
Finish SASL support.
* dico/autologin.c (parse_autologin): Support for new keywords: realm, service and host. * dico/cmdline.opt: New options --sasl, --nosasl. * dico/connect.c (dict_auth): Rewrite authention to avoid dependency from "auth" capability. (auth_cred_free): Free new auth_cred members. (get_credentials): Rename to auth_cred_get, make global. * dico/dico-priv.h (struct auth_cred): New fields service, realm and hostname. (GETCRED_OK, GETCRED_FAIL, GETCRED_NOAUTH): New defines. (auth_cred_get, auth_cred_free): New prototypes. (set_bool): Change return type to int. (ds_sasl): New prototype. (saslauth): Change signature. * dico/func.c (set_bool): Change return type to int. (ds_sasl): New function. * dico/saslauth.c (callback): Use new auth_cred members. (saslauth): Rename to saslauth0. (saslauth, sasl_enable, sasl_enabled_p): New functions. * dico/shell.c: Add `sasl' command. * dicod/main.c (get_full_hostname): Moved to libxdico. * include/xdico.h (xdico_local_hostname): New prototype. * lib/Makefile.am (libxdico_a_SOURCES): Add xhostname.c.
Diffstat (limited to 'dico')
-rw-r--r--dico/autologin.c167
-rw-r--r--dico/cmdline.opt12
-rw-r--r--dico/connect.c73
-rw-r--r--dico/dico-priv.h17
-rw-r--r--dico/func.c45
-rw-r--r--dico/saslauth.c70
-rw-r--r--dico/shell.c12
7 files changed, 284 insertions, 112 deletions
diff --git a/dico/autologin.c b/dico/autologin.c
index ca4dafd..232589f 100644
--- a/dico/autologin.c
+++ b/dico/autologin.c
@@ -88,6 +88,47 @@ argv_expand(int *pargc, char ***pargv, int xargc, char **xargv)
*pargv = nargv;
}
+enum kw_tok {
+ kw_login,
+ kw_password,
+ kw_noauth,
+ kw_nosasl,
+ kw_sasl,
+ kw_mechanism,
+ kw_realm,
+ kw_service,
+ kw_host
+};
+
+struct keyword {
+ char *name;
+ int arg;
+ enum kw_tok tok;
+};
+
+static struct keyword kwtab[] = {
+ { "login", 1, kw_login },
+ { "password", 1, kw_password },
+ { "noauth", 0, kw_noauth },
+ { "nosasl", 0, kw_nosasl },
+ { "sasl", 0, kw_sasl },
+ { "mechanism", 1, kw_mechanism },
+ { "realm", 1, kw_realm },
+ { "service", 1, kw_service },
+ { "host", 1, kw_host },
+ { NULL }
+};
+
+static struct keyword *
+findkw(const char *name)
+{
+ struct keyword *p;
+ for (p = kwtab; p->name; p++)
+ if (strcmp(p->name, name) == 0)
+ return p;
+ return NULL;
+}
+
/* Parse netrc-like autologin file and set up user and key accordingly. */
int
parse_autologin(const char *filename, char *host, struct auth_cred *pcred,
@@ -192,68 +233,90 @@ parse_autologin(const char *filename, char *host, struct auth_cred *pcred,
if (p_argv) {
line = def_line;
+ pcred->sasl = sasl_enabled_p();
while (*p_argv) {
if (strcmp(*p_argv, "\n") == 0) {
line++;
p_argv++;
- } if (strcmp(*p_argv, "login") == 0) {
- if (!p_argv[1]) {
+ } else {
+ struct keyword *kw = findkw(*p_argv);
+ char *arg;
+
+ if (!kw) {
dico_log(L_ERR, 0,
- _("%s:%d: %s without argument"),
- filename, line, p_argv[0]);
- break;
+ _("%s:%d: unknown keyword"), filename, line);
+ p_argv++;
+ continue;
}
- pcred->user = xstrdup(p_argv[1]);
- p_argv += 2;
- flags |= AUTOLOGIN_USERNAME;
- } else if (strcmp(*p_argv, "password") == 0) {
- if (!p_argv[1]) {
- dico_log(L_ERR, 0,
- _("%s:%d: %s without argument"),
- filename, line, p_argv[0]);
+
+ if (kw->arg) {
+ if (!p_argv[1]) {
+ dico_log(L_ERR, 0,
+ _("%s:%d: %s without argument"),
+ filename, line, p_argv[0]);
+ break;
+ }
+ arg = p_argv[1];
+ p_argv += 2;
+ } else
+ p_argv++;
+
+ switch (kw->tok) {
+ case kw_login:
+ pcred->user = xstrdup(arg);
+ flags |= AUTOLOGIN_USERNAME;
break;
- }
- pcred->pass = xstrdup(p_argv[1]);
- flags |= AUTOLOGIN_PASSWORD;
- p_argv += 2;
- } else if (strcmp(*p_argv, "noauth") == 0) {
- flags |= AUTOLOGIN_NOAUTH;
- p_argv++;
- } else if (strcmp(*p_argv, "nosasl") == 0) {
- pcred->sasl = 0;
- p_argv++;
- } else if (strcmp(*p_argv, "sasl") == 0) {
- pcred->sasl = 1;
- p_argv++;
- } else if (strcmp(*p_argv, "mechanism") == 0) {
- int i, c;
- char **v;
+
+ case kw_password:
+ pcred->pass = xstrdup(arg);
+ flags |= AUTOLOGIN_PASSWORD;
+ break;
+
+ case kw_service:
+ pcred->service = xstrdup(arg);
+ break;
+
+ case kw_realm:
+ pcred->realm = xstrdup(arg);
+ break;
+
+ case kw_host:
+ pcred->hostname = xstrdup(arg);
+ break;
+
+ case kw_noauth:
+ flags |= AUTOLOGIN_NOAUTH;
+ break;
+
+ case kw_nosasl:
+ pcred->sasl = 0;
+ break;
+
+ case kw_sasl:
+ pcred->sasl = 1;
+ break;
+
+ case kw_mechanism: {
+ int i, c;
+ char **v;
- if (!p_argv[1]) {
- dico_log(L_ERR, 0,
- _("%s:%d: %s without argument"),
- filename, line, p_argv[0]);
+ if (!(flags & AUTOLOGIN_MECH)) {
+ pcred->mech = xdico_list_create();
+ flags |= AUTOLOGIN_MECH;
+ }
+ if (dico_argcv_get(arg, ",", NULL, &c, &v)) {
+ dico_log(L_ERR, 0,
+ _("%s:%d: not enough memory"),
+ filename, line);
+ exit(1);
+ }
+ for (i = 0; i < c; i++)
+ xdico_list_append(pcred->mech, v[i]);
+
+ free(v);
break;
+ }
}
- if (!(flags & AUTOLOGIN_MECH)) {
- pcred->mech = xdico_list_create();
- flags |= AUTOLOGIN_MECH;
- }
- if (dico_argcv_get(p_argv[1], ",", NULL, &c, &v)) {
- dico_log(L_ERR, 0,
- _("%s:%d: not enough memory"),
- filename, line);
- exit(1);
- }
- for (i = 0; i < c; i++)
- xdico_list_append(pcred->mech, v[i]);
-
- free(v);
- p_argv += 2;
- } else {
- dico_log(L_ERR, 0,
- _("%s:%d: unknown keyword"), filename, line);
- p_argv++;
}
}
}
diff --git a/dico/cmdline.opt b/dico/cmdline.opt
index fa2b48f..dfbc135 100644
--- a/dico/cmdline.opt
+++ b/dico/cmdline.opt
@@ -123,6 +123,18 @@ BEGIN
noauth_option = 1;
END
+OPTION(sasl,,
+ [<Enable SASL authentication (default).>])
+BEGIN
+ sasl_enable(1);
+END
+
+OPTION(nosasl,,
+ [<Disable SASL authentication.>])
+BEGIN
+ sasl_enable(0);
+END
+
OPTION(user,u,NAME,
[<Set user name for authentication.>])
BEGIN
diff --git a/dico/connect.c b/dico/connect.c
index 1b9c12d..0370d40 100644
--- a/dico/connect.c
+++ b/dico/connect.c
@@ -93,16 +93,35 @@ apop_auth(struct dict_connection *conn, struct auth_cred *cred)
}
static int
-dict_auth(struct dict_connection *conn, struct auth_cred *cred)
+dict_auth(struct dict_connection *conn, dico_url_t url)
{
- int rc = saslauth(conn, cred);/*FIXME: ignored */
+ int rc = saslauth(conn, url);
+
switch (rc) {
case AUTH_OK:
return 0;
case AUTH_CONT:
- return apop_auth(conn, cred);
+ if (dict_capa(conn, "auth")) {
+ struct auth_cred cred;
+
+ switch (auth_cred_get(url->host, &cred)) {
+ case GETCRED_OK:
+ rc = apop_auth(conn, &cred);
+ auth_cred_free(&cred);
+ return rc;
+
+ case GETCRED_FAIL:
+ dico_log(L_WARN, 0,
+ _("Not enough credentials for authentication"));
+ break;
+ case GETCRED_NOAUTH:
+ break;
+ }
+ }
+ return 0;
+
case AUTH_FAIL:
return 1;
}
@@ -161,19 +180,26 @@ auth_cred_dup(struct auth_cred *dst, const struct auth_cred *src)
dst->pass = src->pass ? xstrdup(src->pass) : NULL;
}
-static void
+static int
+_cred_free(void *item, void *data)
+{
+ free(item);
+ return 0;
+}
+
+void
auth_cred_free(struct auth_cred *cred)
{
free(cred->user);
free(cred->pass);
+ dico_list_destroy(&cred->mech, _cred_free, NULL);
+ free(cred->service);
+ free(cred->realm);
+ free(cred->hostname);
}
-#define GETCRED_OK 0
-#define GETCRED_FAIL 1
-#define GETCRED_NOAUTH 2
-
-static int
-get_credentials(char *host, struct auth_cred *cred)
+int
+auth_cred_get(char *host, struct auth_cred *cred)
{
memset(cred, 0, sizeof(cred[0]));
auth_cred_dup(cred, &default_cred);
@@ -316,29 +342,10 @@ dict_connect(struct dict_connection **pconn, dico_url_t url)
obstack_init(&conn->stk);
- if (!noauth_option && dict_capa(conn, "auth")) {
- struct auth_cred cred;
- int rc;
-
- switch (get_credentials(url->host, &cred)) {
- case GETCRED_OK:
- rc = dict_auth(conn, &cred);
- auth_cred_free(&cred);
- if (rc) {
- dico_log(L_ERR, 0, _("Authentication failed"));
- dict_conn_close(conn);
- return 1;
- }
- break;
-
- case GETCRED_FAIL:
- dico_log(L_WARN, 0,
- _("Not enough credentials for authentication"));
- break;
-
- case GETCRED_NOAUTH:
- break;
- }
+ if (!noauth_option && dict_auth(conn, url)) {
+ dico_log(L_ERR, 0, _("Authentication failed"));
+ dict_conn_close(conn);
+ return 1;
}
*pconn = conn;
diff --git a/dico/dico-priv.h b/dico/dico-priv.h
index 2ed23dc..e9104b8 100644
--- a/dico/dico-priv.h
+++ b/dico/dico-priv.h
@@ -117,6 +117,9 @@ struct auth_cred {
char *pass;
int sasl;
dico_list_t mech;
+ char *service;
+ char *realm;
+ char *hostname;
};
struct funtab {
@@ -164,6 +167,13 @@ int dict_match(struct dict_connection *conn, char *database, char *strategy,
char *get_homedir(void);
int ds_tilde_expand(const char *str, char **output);
+#define GETCRED_OK 0
+#define GETCRED_FAIL 1
+#define GETCRED_NOAUTH 2
+
+int auth_cred_get(char *host, struct auth_cred *cred);
+void auth_cred_free(struct auth_cred *cred);
+
/* lookup.c */
int dict_lookup_url(dico_url_t url);
int dict_word(char *word);
@@ -195,7 +205,7 @@ char **dict_completion_matches(int argc, char **argv, int ws,
/* func.c */
int ensure_connection(void);
-void set_bool(int *pval, char *str);
+int set_bool(int *pval, char *str);
void ds_silent_close(void);
void ds_open(int argc, char **argv);
void ds_close(int argc, char **argv);
@@ -212,6 +222,7 @@ void ds_warranty(int argc, char **argv);
void ds_show_db(int argc, char **argv);
void ds_show_strat(int argc, char **argv);
void ds_show_info(int argc, char **argv);
+void ds_sasl(int argc, char **argv);
char **ds_compl_database(int argc, char **argv, int ws);
char **ds_compl_strategy(int argc, char **argv, int ws);
@@ -225,4 +236,6 @@ dico_stream_t create_pager_stream(size_t nlines);
#define AUTH_FAIL 1
#define AUTH_CONT 2
-int saslauth(struct dict_connection *conn, struct auth_cred *cred);
+int saslauth(struct dict_connection *conn, dico_url_t url);
+void sasl_enable(int val);
+int sasl_enabled_p(void);
diff --git a/dico/func.c b/dico/func.c
index 1dbc9d6..e9bcb56 100644
--- a/dico/func.c
+++ b/dico/func.c
@@ -18,6 +18,24 @@
static struct dict_connection *conn;
+int
+set_bool(int *pval, char *str)
+{
+ if (strcmp(str, "yes") == 0
+ || strcmp(str, "on") == 0
+ || strcmp(str, "true") == 0)
+ *pval = 1;
+ else if (strcmp(str, "no") == 0
+ || strcmp(str, "off") == 0
+ || strcmp(str, "false") == 0)
+ *pval = 0;
+ else {
+ script_error(_("Expected boolean value"));
+ return 1;
+ }
+ return 0;
+}
+
void
ds_silent_close()
{
@@ -149,6 +167,18 @@ ds_autologin(int argc, char **argv)
}
void
+ds_sasl(int argc, char **argv)
+{
+ if (argc == 1) {
+ printf("%s\n", sasl_enabled_p() ? _("on") : _("off"));
+ } else {
+ int val;
+ if (set_bool(&val, argv[1]) == 0)
+ sasl_enable(val);
+ }
+}
+
+void
ds_database(int argc, char **argv)
{
if (argc == 1) {
@@ -213,21 +243,6 @@ ds_compl_strategy(int argc, char **argv, int ws)
void
-set_bool(int *pval, char *str)
-{
- if (strcmp(str, "yes") == 0
- || strcmp(str, "on") == 0
- || strcmp(str, "true") == 0)
- *pval = 1;
- else if (strcmp(str, "no") == 0
- || strcmp(str, "off") == 0
- || strcmp(str, "false") == 0)
- *pval = 0;
- else
- script_error(_("Expected boolean value"));
-}
-
-void
ds_transcript(int argc, char **argv)
{
if (argc == 1)
diff --git a/dico/saslauth.c b/dico/saslauth.c
index 9ac4979..c2a9675 100644
--- a/dico/saslauth.c
+++ b/dico/saslauth.c
@@ -105,12 +105,15 @@ selectmech(struct dict_connection *conn, Gsasl *ctx, struct auth_cred *cred)
return mech;
}
+#define CRED_HOSTNAME(c) ((c)->hostname ? (c)->hostname : \
+ ((c)->hostname = xdico_local_hostname()))
+
static int
callback(Gsasl *ctx, Gsasl_session *sctx, Gsasl_property prop)
{
int rc = GSASL_NO_CALLBACK;
struct auth_cred *cred = gsasl_callback_hook_get(ctx);
-#define hostname "Trurl.gnu.org.ua"
+
switch (prop) {
case GSASL_PASSWORD:
gsasl_property_set(sctx, prop, cred->pass);
@@ -124,17 +127,19 @@ callback(Gsasl *ctx, Gsasl_session *sctx, Gsasl_property prop)
break;
case GSASL_SERVICE:
- gsasl_property_set(sctx, prop, "dico");//FIXME: configurable
+ gsasl_property_set(sctx, prop,
+ cred->service ? cred->service : "dico");
rc = GSASL_OK;
break;
case GSASL_REALM:
- gsasl_property_set(sctx, prop, hostname);
+ gsasl_property_set(sctx, prop,
+ cred->realm ? cred->realm : CRED_HOSTNAME(cred));
rc = GSASL_OK;
break;
case GSASL_HOSTNAME:
- gsasl_property_set(sctx, prop, hostname);
+ gsasl_property_set(sctx, prop, CRED_HOSTNAME(cred));
rc = GSASL_OK;
break;
@@ -234,7 +239,7 @@ do_gsasl_auth(Gsasl *ctx, struct dict_connection *conn, char *mech)
}
int
-saslauth(struct dict_connection *conn, struct auth_cred *cred)
+saslauth0(struct dict_connection *conn, struct auth_cred *cred)
{
Gsasl *ctx;
int rc;
@@ -263,10 +268,63 @@ saslauth(struct dict_connection *conn, struct auth_cred *cred)
/* FIXME */
return rc == 0 ? AUTH_OK : AUTH_FAIL;
}
+
+int
+saslauth(struct dict_connection *conn, dico_url_t url)
+{
+ int rc = AUTH_FAIL;
+ struct auth_cred cred;
+
+ switch (auth_cred_get(url->host, &cred)) {
+ case GETCRED_OK:
+ if (cred.sasl) {
+ rc = saslauth0(conn, &cred);
+ auth_cred_free(&cred);
+ } else
+ rc = AUTH_CONT;
+ break;
+
+ case GETCRED_FAIL:
+ dico_log(L_WARN, 0,
+ _("Not enough credentials for authentication"));
+ break;
+
+ case GETCRED_NOAUTH:
+ rc = AUTH_OK;
+ }
+ return rc;
+}
+
+static int sasl_enable_state = 1;
+
+void
+sasl_enable(int val)
+{
+ sasl_enable_state = 1;
+}
+
+int
+sasl_enabled_p()
+{
+ return sasl_enable_state;
+}
+
#else
int
-saslauth(struct dict_connection *conn, struct auth_cred *cred)
+saslauth(struct dict_connection *conn, dico_url_t url)
{
return AUTH_CONT;
}
+
+void
+sasl_enable(int val)
+{
+ dico_log(L_WARN, 0, _("Dico compiled without SASL support"));
+}
+
+int
+sasl_enabled_p()
+{
+ return 0;
+}
#endif
diff --git a/dico/shell.c b/dico/shell.c
index d7afc27..828503c 100644
--- a/dico/shell.c
+++ b/dico/shell.c
@@ -49,10 +49,6 @@ struct funtab funtab[] = {
NULL,
N_("Close the connection."),
ds_close, },
- { "autologin", 1, 2,
- N_("[FILE]"),
- N_("Set or display autologin file name."),
- ds_autologin,},
{ "database", 1, 2,
N_("[NAME]"),
N_("Set or display current database name."),
@@ -93,6 +89,14 @@ struct funtab funtab[] = {
N_("STRING"),
N_("Change or display pager settings."),
ds_pager, no_compl },
+ { "autologin", 1, 2,
+ N_("[FILE]"),
+ N_("Set or display autologin file name."),
+ ds_autologin,},
+ { "sasl", 1, 2,
+ N_("[BOOL]"),
+ N_("Enable SASL authentication."),
+ ds_sasl, no_compl },
#ifdef WITH_READLINE
{ "history", 1, 1,
NULL,

Return to:

Send suggestions and report system problems to the System administrator.