2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <windows.h>
\r
11 #include "krb_auth.h"
\r
12 #include "afs_tokens.h"
\r
13 #include "cm_config.h"
\r
16 #define AFS_KERBEROS_ENV
\r
18 #define KABADARGUMENT 1
\r
19 #define KLOGEXIT(code) exit(code)
\r
23 static int zero_argc;
\r
24 static char **zero_argv;
\r
26 void main (argc, argv)
\r
29 { struct cmd_syndesc *ts;
\r
36 /* Start up sockets */
\r
37 WSAStartup(0x0101, &WSAjunk);
\r
39 ts = cmd_CreateSyntax((char *) 0, CommandProc, 0, "obtain Kerberos authentication");
\r
42 #define aPRINCIPAL 1
\r
53 cmd_AddParm(ts, "-x", CMD_FLAG, CMD_OPTIONAL, "(obsolete, noop)");
\r
54 cmd_Seek(ts, aPRINCIPAL);
\r
55 cmd_AddParm(ts, "-principal", CMD_SINGLE, CMD_OPTIONAL, "user name");
\r
56 cmd_AddParm(ts, "-password", CMD_SINGLE, CMD_OPTIONAL, "user's password");
\r
57 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
\r
58 cmd_AddParm(ts, "-servers", CMD_LIST, CMD_OPTIONAL, "explicit list of servers");
\r
59 cmd_AddParm(ts, "-pipe", CMD_FLAG, CMD_OPTIONAL, "read password from stdin");
\r
60 cmd_AddParm(ts, "-silent", CMD_FLAG, CMD_OPTIONAL, "silent operation");
\r
61 cmd_AddParm(ts, "-lifetime", CMD_SINGLE, CMD_OPTIONAL, "ticket lifetime in hh[:mm[:ss]]");
\r
62 cmd_AddParm(ts, "-setpag", CMD_FLAG, CMD_OPTIONAL, "Create a new setpag before authenticating");
\r
63 cmd_AddParm(ts, "-tmp", CMD_FLAG, CMD_OPTIONAL, "write Kerberos-style ticket file in /tmp");
\r
65 code = cmd_Dispatch(argc, argv);
\r
69 static char *getpipepass() {
\r
70 static char gpbuf[BUFSIZ];
\r
71 /* read a password from stdin, stop on \n or eof */
\r
73 memset(gpbuf, 0, sizeof(gpbuf));
\r
74 for(i=0; i<(sizeof(gpbuf)-1); i++) {
\r
76 if (tc == '\n' || tc == EOF) break;
\r
82 /* good_gets is like gets except that it take a max string length and won't
\r
83 * write past the end of its input buffer. It returns a variety of negative
\r
84 * numbers in case of errors and zero if there was no characters read (a blank
\r
85 * line for instance). Otherwise it returns the length of the string read in.
\r
88 static int good_gets (s, max)
\r
91 { int l; /* length of string read */
\r
92 if (!fgets (s, max, stdin)) {
\r
93 if (feof(stdin)) return EOF; /* EOF on input, nothing read */
\r
94 else return -2; /* I don't think this can happen */
\r
97 if (l && (s[l-1] == '\n')) s[--l] = 0;
\r
101 static int read_pw_string(char *s, int max)
\r
108 h = GetStdHandle (STD_INPUT_HANDLE);
\r
109 GetConsoleMode (h, &md);
\r
110 SetConsoleMode (h, md & ~ENABLE_ECHO_INPUT);
\r
113 printf("Password:");
\r
115 if (good_gets(s, max) <= 0) {
\r
116 printf("\n"); fflush(stdout);
\r
117 if (feof (stdin)) break; /* just give up */
\r
118 else continue; /* try again: blank line */
\r
127 SetConsoleMode (h, md);
\r
128 printf("\n"); fflush(stdout);
\r
130 s[max-1] = 0; /* force termination */
\r
134 CommandProc (as, arock)
\r
136 struct cmd_syndesc *as;
\r
138 char name[MAXKTCNAMELEN];
\r
139 char defaultCell[256];
\r
140 char realm[MAXKTCREALMLEN];
\r
143 int lifetime; /* requested ticket lifetime */
\r
145 char passwd[BUFSIZ];
\r
147 static char rn[] = "klog"; /*Routine name*/
\r
148 static int Pipe = 0; /* reading from a pipe */
\r
149 static int Silent = 0; /* Don't want error messages */
\r
151 int foundPassword = 0; /*Not yet, anyway*/
\r
152 int foundExplicitCell = 0; /*Not yet, anyway*/
\r
153 int writeTicketFile = 0; /* write ticket file to /tmp */
\r
154 int password_expires = -1;
\r
156 char *reason; /* string describing errors */
\r
158 /* blow away command line arguments */
\r
159 for (i=1; i<zero_argc; i++) memset (zero_argv[i], 0, strlen(zero_argv[i]));
\r
162 /* first determine quiet flag based on -silent switch */
\r
163 Silent = (as->parms[aSILENT].itemsp ? 1 : 0);
\r
164 Pipe = (as->parms[aPIPE].itemsp ? 1 : 0);
\r
166 /* Determine if we should also do a setpag based on -setpag switch */
\r
167 dosetpag = (as->parms[aSETPAG].itemsp ? 1 : 0);
\r
169 if (as->parms[aTMP].itemsp) {
\r
170 writeTicketFile = 1;
\r
173 cm_GetRootCellName(defaultCell);
\r
175 /* Parse our arguments. */
\r
177 if (as->parms[aCELL].itemsp) {
\r
179 * cell name explicitly mentioned; take it in if no other cell name
\r
180 * has already been specified and if the name actually appears. If
\r
181 * the given cell name differs from our own, we don't do a lookup.
\r
183 foundExplicitCell = 1;
\r
184 strncpy (realm, as->parms[aCELL].itemsp->data, sizeof(realm));
\r
187 if (as->parms[aSERVERS].itemsp) {
\r
188 fprintf (stderr, "SERVERS option not available.\n");
\r
191 if (as->parms[aPRINCIPAL].itemsp) {
\r
192 strcpy(name, as->parms[aPRINCIPAL].itemsp->data);
\r
194 /* No explicit name provided. */
\r
195 DWORD size = GetEnvironmentVariable("USERNAME", name, sizeof(name) - 1);
\r
196 if (size <= 0 || size >= sizeof(name))
\r
197 KLOGEXIT( KABADARGUMENT );
\r
200 if (as->parms[aPASSWORD].itemsp) {
\r
202 * Current argument is the desired password string. Remember it in
\r
203 * our local buffer, and zero out the argument string - anyone can
\r
204 * see it there with ps!
\r
207 strncpy (passwd, as->parms[aPASSWORD].itemsp->data, sizeof(passwd));
\r
208 memset (as->parms[aPASSWORD].itemsp->data, 0,
\r
209 strlen(as->parms[aPASSWORD].itemsp->data));
\r
212 if (as->parms[aLIFETIME].itemsp) {
\r
213 char *life = as->parms[aLIFETIME].itemsp->data;
\r
214 char *sp; /* string ptr to rest of life */
\r
215 lifetime = 3600*strtol (life, &sp, 0); /* hours */
\r
218 if (!Silent) fprintf (stderr, "%s: translating '%s' to lifetime failed\n",
\r
220 return KABADARGUMENT;
\r
223 life = sp+1; /* skip the colon */
\r
224 lifetime += 60*strtol (life, &sp, 0); /* minutes */
\r
225 if (sp == life) goto bad_lifetime;
\r
228 lifetime += strtol (life, &sp, 0); /* seconds */
\r
229 if (sp == life) goto bad_lifetime;
\r
230 if (*sp) goto bad_lifetime;
\r
231 } else if (*sp) goto bad_lifetime;
\r
232 } else if (*sp) goto bad_lifetime;
\r
233 if (lifetime > MAXKTCTICKETLIFETIME) {
\r
236 "%s: a lifetime of %.2f hours is too long, must be less than %d.\n",
\r
237 rn, (double)lifetime/3600.0, MAXKTCTICKETLIFETIME/3600);
\r
238 KLOGEXIT( KABADARGUMENT );
\r
240 } else lifetime = 0;
\r
242 if (!foundExplicitCell) strcpy (realm, defaultCell);
\r
244 /* Get the password if it wasn't provided. */
\r
245 if (!foundPassword) {
\r
247 strncpy(passwd, getpipepass(), sizeof(passwd));
\r
250 if (read_pw_string(passwd, sizeof(passwd)))
\r
251 reason = "can't read password from terminal";
\r
252 else if (strlen(passwd) == 0)
\r
253 reason = "zero length password is illegal";
\r
257 fprintf (stderr, "Unable to login because %s.\n", reason);
\r
258 KLOGEXIT( KABADARGUMENT );
\r
263 code = ka_UserAuthenticateGeneral (0, name, "", realm, passwd, lifetime,
\r
264 &password_expires, 0, &reason);
\r
265 memset (passwd, 0, sizeof(passwd));
\r
269 "Unable to authenticate to AFS because %s.\n", reason);
\r
274 #ifndef AFS_KERBEROS_ENV
\r
275 if (writeTicketFile) {
\r
276 code = krb_write_ticket_file (realm);
\r
279 com_err (rn, code, "writing Kerberos ticket file");
\r
280 else fprintf (stderr, "Wrote ticket file to /tmp\n");
\r
285 #ifdef DEBUGEXPIRES
\r
286 if (password_expires >= 0) {
\r
287 printf ("password expires at %ld\n", password_expires);
\r
289 #endif /* DEBUGEXPIRES */
\r
294 /* dummies to substitute for OSI */
\r
295 void *osi_Alloc(int sz) {
\r
298 void osi_Free(void *vs, int sz) {
\r