]> diplodocus.org Git - nmh/blob - uip/mhlogin.c
a08305c846d318fd0fa582b40fa4a131fa5db8ac
[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", 1, SASLMECHSW) \
17 X("authservice", -11, AUTHSERVICESW) \
18 X("snoop", 1, SNOOPSW) \
19 X("help", 1, HELPSW) \
20 X("version", 1, VERSIONSW) \
21
22 #define X(sw, minchars, id) id,
23 DEFINE_SWITCH_ENUM(MHLOGIN);
24 #undef X
25
26 #define X(sw, minchars, id) { sw, minchars, id },
27 DEFINE_SWITCH_ARRAY(MHLOGIN, switches);
28 #undef X
29
30 #ifdef OAUTH_SUPPORT
31 /* XXX copied from install-mh.c */
32 static char *
33 geta (void)
34 {
35 char *cp;
36 static char line[BUFSIZ];
37
38 if (fgets(line, sizeof(line), stdin) == NULL)
39 done (1);
40 if ((cp = strchr(line, '\n')))
41 *cp = 0;
42 return line;
43 }
44
45 static int
46 do_login(const char *svc, int snoop)
47 {
48 char *fn, *code;
49 mh_oauth_ctx *ctx;
50 mh_oauth_cred *cred;
51 FILE *cred_file;
52 int failed_to_lock = 0;
53 const char *url;
54
55 if (svc == NULL) {
56 adios(NULL, "missing -authservice switch");
57 }
58
59 if (!mh_oauth_new(&ctx, svc)) {
60 adios(NULL, mh_oauth_get_err_string(ctx));
61 }
62
63 if (snoop) {
64 mh_oauth_log_to(stderr, ctx);
65 }
66
67 fn = getcpy(mh_oauth_cred_fn(ctx));
68
69 if ((url = mh_oauth_get_authorize_url(ctx)) == NULL) {
70 adios(NULL, mh_oauth_get_err_string(ctx));
71 }
72
73 printf("Load the following URL in your browser and authorize nmh"
74 " to access %s:\n"
75 "\n%s\n\n"
76 "Enter the authorization code: ",
77 mh_oauth_svc_display_name(ctx), url);
78 fflush(stdout);
79 code = geta();
80
81 while ((cred = mh_oauth_authorize(code, ctx)) == NULL
82 && mh_oauth_get_err_code(ctx) == MH_OAUTH_BAD_GRANT) {
83 printf("Code rejected; try again? ");
84 fflush(stdout);
85 code = geta();
86 }
87 if (cred == NULL) {
88 advise(NULL, "error exchanging code for OAuth2 token");
89 adios(NULL, mh_oauth_get_err_string(ctx));
90 }
91
92 cred_file = lkfopendata(fn, "w", &failed_to_lock);
93 if (cred_file == NULL || failed_to_lock) {
94 adios(fn, "oops");
95 }
96 if (!mh_oauth_cred_save(cred_file, cred)) {
97 adios(NULL, mh_oauth_get_err_string(ctx));
98 }
99 if (lkfclosedata(cred_file, fn) != 0) {
100 adios (fn, "oops");
101 }
102
103 mh_oauth_cred_free(cred);
104 mh_oauth_free(ctx);
105
106 return 0;
107 }
108 #endif
109
110 int
111 main(int argc, char **argv)
112 {
113 char *cp, **argp, **arguments;
114 char *saslmech = NULL, *svc = NULL;
115 int snoop = 0;
116
117 if (nmh_init(argv[0], 1)) { return 1; }
118
119 arguments = getarguments (invo_name, argc, argv, 1);
120 argp = arguments;
121
122 while ((cp = *argp++)) {
123 if (*cp == '-') {
124 char help[BUFSIZ];
125 switch (smatch (++cp, switches)) {
126 case AMBIGSW:
127 ambigsw (cp, switches);
128 done (1);
129 case UNKWNSW:
130 adios (NULL, "-%s unknown", cp);
131
132 case HELPSW:
133 snprintf(help, sizeof(help), "%s [switches]",
134 invo_name);
135 print_help (help, switches, 1);
136 done (0);
137 case VERSIONSW:
138 print_version(invo_name);
139 done (0);
140
141 case SASLMECHSW:
142 if (!(saslmech = *argp++) || *saslmech == '-')
143 adios (NULL, "missing argument to %s", argp[-2]);
144 continue;
145
146 case AUTHSERVICESW:
147 if (!(svc = *argp++) || *svc == '-')
148 adios (NULL, "missing argument to %s", argp[-2]);
149 continue;
150
151 case SNOOPSW:
152 snoop++;
153 continue;
154 }
155 }
156 adios(NULL, "extraneous arguments");
157 }
158
159 #ifdef OAUTH_SUPPORT
160 return do_login(svc, snoop);
161 #else
162 NMH_UNUSED(svc);
163 NMH_UNUSED(snoop);
164 adios(NULL, "not built with OAuth support");
165 return 1;
166 #endif
167 }