]> diplodocus.org Git - nmh/blob - uip/mhlogin.c
fix mhlogin -browser test
[nmh] / uip / mhlogin.c
1 /*
2 * mhlogin.c -- login to external (OAuth) services
3 *
4 * This code is Copyright (c) 2014, by the authors of nmh. See the
5 * COPYRIGHT file in the root directory of the nmh distribution for
6 * complete copyright information.
7 */
8
9 #include <stdio.h>
10 #include <string.h>
11
12 #include <h/mh.h>
13 #include <h/oauth.h>
14
15 #define MHLOGIN_SWITCHES \
16 X("saslmech", 0, SASLMECHSW) \
17 X("authservice", 0, AUTHSERVICESW) \
18 X("browser", 0, BROWSERSW) \
19 X("snoop", 0, SNOOPSW) \
20 X("help", 0, HELPSW) \
21 X("version", 0, VERSIONSW) \
22
23 #define X(sw, minchars, id) id,
24 DEFINE_SWITCH_ENUM(MHLOGIN);
25 #undef X
26
27 #define X(sw, minchars, id) { sw, minchars, id },
28 DEFINE_SWITCH_ARRAY(MHLOGIN, switches);
29 #undef X
30
31 #ifdef OAUTH_SUPPORT
32 /* XXX copied from install-mh.c */
33 static char *
34 geta (void)
35 {
36 char *cp;
37 static char line[BUFSIZ];
38
39 if (fgets(line, sizeof(line), stdin) == NULL)
40 done (1);
41 if ((cp = strchr(line, '\n')))
42 *cp = 0;
43 return line;
44 }
45
46 static int
47 do_login(const char *svc, const char *browser, int snoop)
48 {
49 char *fn, *code;
50 mh_oauth_ctx *ctx;
51 mh_oauth_cred *cred;
52 FILE *cred_file;
53 int failed_to_lock = 0;
54 const char *url;
55
56 if (svc == NULL) {
57 adios(NULL, "missing -authservice switch");
58 }
59
60 if (!mh_oauth_new(&ctx, svc)) {
61 adios(NULL, mh_oauth_get_err_string(ctx));
62 }
63
64 if (snoop) {
65 mh_oauth_log_to(stderr, ctx);
66 }
67
68 fn = getcpy(mh_oauth_cred_fn(ctx));
69
70 if ((url = mh_oauth_get_authorize_url(ctx)) == NULL) {
71 adios(NULL, mh_oauth_get_err_string(ctx));
72 }
73
74 if (browser) {
75 char *command = concat(browser, " '", url, "'", NULL);
76 int status = OK;
77
78 printf("Follow the prompts in your browser to authorize nmh"
79 " to access %s.\n",
80 mh_oauth_svc_display_name(ctx));
81 sleep(1);
82
83 status = system(command);
84 free(command);
85
86 if (status != OK) {
87 adios ((char *) browser, "SYSTEM");
88 }
89 } else {
90 printf("Load the following URL in your browser and authorize nmh"
91 " to access %s:\n\n%s\n\n",
92 mh_oauth_svc_display_name(ctx), url);
93 }
94 printf("Enter the authorization code: ");
95 fflush(stdout);
96 code = geta();
97
98 while ((cred = mh_oauth_authorize(code, ctx)) == NULL
99 && mh_oauth_get_err_code(ctx) == MH_OAUTH_BAD_GRANT) {
100 printf("Code rejected; try again? ");
101 fflush(stdout);
102 code = geta();
103 }
104 if (cred == NULL) {
105 advise(NULL, "error exchanging code for OAuth2 token");
106 adios(NULL, mh_oauth_get_err_string(ctx));
107 }
108
109 cred_file = lkfopendata(fn, "w", &failed_to_lock);
110 if (cred_file == NULL || failed_to_lock) {
111 adios(fn, "oops");
112 }
113 if (!mh_oauth_cred_save(cred_file, cred)) {
114 adios(NULL, mh_oauth_get_err_string(ctx));
115 }
116 if (lkfclosedata(cred_file, fn) != 0) {
117 adios (fn, "oops");
118 }
119
120 mh_oauth_cred_free(cred);
121 mh_oauth_free(ctx);
122
123 return 0;
124 }
125 #endif
126
127 int
128 main(int argc, char **argv)
129 {
130 char *cp, **argp, **arguments;
131 const char *saslmech = NULL, *svc = NULL, *browser = NULL;
132 int snoop = 0;
133
134 if (nmh_init(argv[0], 1)) { return 1; }
135
136 arguments = getarguments (invo_name, argc, argv, 1);
137 argp = arguments;
138
139 while ((cp = *argp++)) {
140 if (*cp == '-') {
141 char help[BUFSIZ];
142 switch (smatch (++cp, switches)) {
143 case AMBIGSW:
144 ambigsw (cp, switches);
145 done (1);
146 case UNKWNSW:
147 adios (NULL, "-%s unknown", cp);
148
149 case HELPSW:
150 snprintf(help, sizeof(help), "%s [switches]",
151 invo_name);
152 print_help (help, switches, 1);
153 done (0);
154 case VERSIONSW:
155 print_version(invo_name);
156 done (0);
157
158 case SASLMECHSW:
159 if (!(saslmech = *argp++) || *saslmech == '-')
160 adios (NULL, "missing argument to %s", argp[-2]);
161 continue;
162
163 case AUTHSERVICESW:
164 if (!(svc = *argp++) || *svc == '-')
165 adios (NULL, "missing argument to %s", argp[-2]);
166 continue;
167
168 case BROWSERSW:
169 if (!(browser = *argp++) || *browser == '-')
170 adios (NULL, "missing argument to %s", argp[-2]);
171 continue;
172
173 case SNOOPSW:
174 snoop++;
175 continue;
176 }
177 }
178 adios(NULL, "extraneous arguments");
179 }
180
181 if (saslmech && strcasecmp(saslmech, "xoauth2")) {
182 /* xoauth is assumed */
183 adios(NULL, "only -saslmech xoauth2 is supported");
184 }
185
186 #ifdef OAUTH_SUPPORT
187 return do_login(svc, browser, snoop);
188 #else
189 NMH_UNUSED(svc);
190 NMH_UNUSED(browser);
191 NMH_UNUSED(snoop);
192 adios(NULL, "not built with OAuth support");
193 return 1;
194 #endif
195 }