]>
diplodocus.org Git - nmh/blob - uip/mhlogin.c
1 /* mhlogin.c -- login to external (OAuth) services
3 * This code is Copyright (c) 2014, by the authors of nmh. See the
4 * COPYRIGHT file in the root directory of the nmh distribution for
5 * complete copyright information.
13 #include "sbr/getarguments.h"
14 #include "sbr/concat.h"
15 #include "sbr/smatch.h"
16 #include "sbr/ambigsw.h"
17 #include "sbr/print_version.h"
18 #include "sbr/print_help.h"
19 #include "sbr/error.h"
23 #include "sbr/lock_file.h"
25 #define MHLOGIN_SWITCHES \
26 X("user username", 0, USERSW) \
27 X("saslmech", 0, SASLMECHSW) \
28 X("authservice", 0, AUTHSERVICESW) \
29 X("browser", 0, BROWSERSW) \
30 X("snoop", 0, SNOOPSW) \
31 X("help", 0, HELPSW) \
32 X("version", 0, VERSIONSW) \
34 #define X(sw, minchars, id) id,
35 DEFINE_SWITCH_ENUM(MHLOGIN
);
38 #define X(sw, minchars, id) { sw, minchars, id },
39 DEFINE_SWITCH_ARRAY(MHLOGIN
, switches
);
43 /* XXX copied from install-mh.c */
47 static char line
[BUFSIZ
];
49 if (fgets(line
, sizeof(line
), stdin
) == NULL
)
51 trim_suffix_c(line
, '\n');
57 do_login(const char *svc
, const char *user
, const char *browser
, int snoop
)
63 int failed_to_lock
= 0;
67 die("missing -authservice switch");
71 die("missing -user switch");
74 if (!mh_oauth_new(&ctx
, svc
)) {
75 die("%s", mh_oauth_get_err_string(ctx
));
79 mh_oauth_log_to(stderr
, ctx
);
82 fn
= mh_oauth_cred_fn(svc
);
84 if ((url
= mh_oauth_get_authorize_url(ctx
)) == NULL
) {
85 die("%s", mh_oauth_get_err_string(ctx
));
89 char *command
= concat(browser
, " '", url
, "'", NULL
);
92 printf("Follow the prompts in your browser to authorize nmh"
94 mh_oauth_svc_display_name(ctx
));
97 status
= system(command
);
101 adios ((char *) browser
, "SYSTEM");
104 printf("Load the following URL in your browser and authorize nmh"
105 " to access %s:\n\n%s\n\n",
106 mh_oauth_svc_display_name(ctx
), url
);
108 fputs("Enter the authorization code: ", stdout
);
113 ((cred
= mh_oauth_authorize(code
, ctx
)) == NULL
114 && mh_oauth_get_err_code(ctx
) == MH_OAUTH_BAD_GRANT
)) {
115 printf(!*code
? "Empty code; try again? " : "Code rejected; try again? ");
120 inform("error exchanging code for OAuth2 token");
121 die("%s", mh_oauth_get_err_string(ctx
));
124 cred_file
= lkfopendata(fn
, "r+", &failed_to_lock
);
125 if (cred_file
== NULL
&& errno
== ENOENT
) {
126 cred_file
= lkfopendata(fn
, "w+", &failed_to_lock
);
128 if (cred_file
== NULL
|| failed_to_lock
) {
131 if (!mh_oauth_cred_save(cred_file
, cred
, user
)) {
132 die("%s", mh_oauth_get_err_string(ctx
));
134 if (lkfclosedata(cred_file
, fn
) != 0) {
139 mh_oauth_cred_free(cred
);
147 main(int argc
, char **argv
)
149 char *cp
, **argp
, **arguments
;
150 const char *user
= NULL
, *saslmech
= NULL
, *svc
= NULL
, *browser
= NULL
;
153 if (nmh_init(argv
[0], true, true)) { return 1; }
155 arguments
= getarguments (invo_name
, argc
, argv
, 1);
158 while ((cp
= *argp
++)) {
161 switch (smatch (++cp
, switches
)) {
163 ambigsw (cp
, switches
);
166 die("-%s unknown", cp
);
169 snprintf(help
, sizeof(help
), "%s [switches]",
171 print_help (help
, switches
, 1);
174 print_version(invo_name
);
178 if (!(user
= *argp
++) || *user
== '-')
179 die("missing argument to %s", argp
[-2]);
183 if (!(saslmech
= *argp
++) || *saslmech
== '-')
184 die("missing argument to %s", argp
[-2]);
188 if (!(svc
= *argp
++) || *svc
== '-')
189 die("missing argument to %s", argp
[-2]);
193 if (!(browser
= *argp
++) || *browser
== '-')
194 die("missing argument to %s", argp
[-2]);
202 die("extraneous arguments");
205 if (saslmech
&& strcasecmp(saslmech
, "xoauth2")) {
206 /* xoauth is assumed */
207 die("only -saslmech xoauth2 is supported");
212 return do_login(svc
, user
, browser
, snoop
);
217 die("not built with OAuth support");