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 <afs/param.h>
14 #include <afs/kautils.h>
15 #include <afs/dirpath.h>
16 #include "cm_config.h"
20 #define AFS_KERBEROS_ENV
22 #define KABADARGUMENT 1
23 #define KLOGEXIT(code) exit(code)
28 static char **zero_argv;
30 void main (argc, argv)
33 { struct cmd_syndesc *ts;
40 /* Start up sockets */
41 WSAStartup(0x0101, &WSAjunk);
43 ts = cmd_CreateSyntax((char *) 0, CommandProc, 0, "obtain Kerberos authentication");
57 cmd_AddParm(ts, "-x", CMD_FLAG, CMD_OPTIONAL, "(obsolete, noop)");
58 cmd_Seek(ts, aPRINCIPAL);
59 cmd_AddParm(ts, "-principal", CMD_SINGLE, CMD_OPTIONAL, "user name");
60 cmd_AddParm(ts, "-password", CMD_SINGLE, CMD_OPTIONAL, "user's password");
61 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
62 cmd_AddParm(ts, "-servers", CMD_LIST, CMD_OPTIONAL, "explicit list of servers");
63 cmd_AddParm(ts, "-pipe", CMD_FLAG, CMD_OPTIONAL, "read password from stdin");
64 cmd_AddParm(ts, "-silent", CMD_FLAG, CMD_OPTIONAL, "silent operation");
65 cmd_AddParm(ts, "-lifetime", CMD_SINGLE, CMD_OPTIONAL, "ticket lifetime in hh[:mm[:ss]]");
66 cmd_AddParm(ts, "-setpag", CMD_FLAG, CMD_OPTIONAL, "Create a new setpag before authenticating");
67 cmd_AddParm(ts, "-tmp", CMD_FLAG, CMD_OPTIONAL, "write Kerberos-style ticket file in /tmp");
69 code = cmd_Dispatch(argc, argv);
73 static char *getpipepass() {
74 static char gpbuf[BUFSIZ];
75 /* read a password from stdin, stop on \n or eof */
77 memset(gpbuf, 0, sizeof(gpbuf));
78 for(i=0; i<(sizeof(gpbuf)-1); i++) {
80 if (tc == '\n' || tc == EOF) break;
86 /* good_gets is like gets except that it take a max string length and won't
87 * write past the end of its input buffer. It returns a variety of negative
88 * numbers in case of errors and zero if there was no characters read (a blank
89 * line for instance). Otherwise it returns the length of the string read in.
92 static int good_gets (s, max)
95 { int l; /* length of string read */
96 if (!fgets (s, max, stdin)) {
97 if (feof(stdin)) return EOF; /* EOF on input, nothing read */
98 else return -2; /* I don't think this can happen */
101 if (l && (s[l-1] == '\n')) s[--l] = 0;
105 static int read_pw_string(char *s, int max)
112 h = GetStdHandle (STD_INPUT_HANDLE);
113 GetConsoleMode (h, &md);
114 SetConsoleMode (h, md & ~ENABLE_ECHO_INPUT);
119 if (good_gets(s, max) <= 0) {
120 printf("\n"); fflush(stdout);
121 if (feof (stdin)) break; /* just give up */
122 else continue; /* try again: blank line */
131 SetConsoleMode (h, md);
132 printf("\n"); fflush(stdout);
134 s[max-1] = 0; /* force termination */
138 CommandProc (as, arock)
140 struct cmd_syndesc *as;
142 char name[MAXKTCNAMELEN];
143 char instance[MAXKTCNAMELEN];
144 char cell[MAXKTCREALMLEN];
145 char defaultCell[256];
146 char realm[MAXKTCREALMLEN];
149 int lifetime; /* requested ticket lifetime */
153 static char rn[] = "klog"; /*Routine name*/
154 static int Pipe = 0; /* reading from a pipe */
155 static int Silent = 0; /* Don't want error messages */
157 int foundPassword = 0; /*Not yet, anyway*/
158 int foundExplicitCell = 0; /*Not yet, anyway*/
159 int writeTicketFile = 0; /* write ticket file to /tmp */
160 int password_expires = -1;
162 char *reason; /* string describing errors */
169 /* blow away command line arguments */
170 for (i=1; i<zero_argc; i++) memset (zero_argv[i], 0, strlen(zero_argv[i]));
173 /* first determine quiet flag based on -silent switch */
174 Silent = (as->parms[aSILENT].items ? 1 : 0);
175 Pipe = (as->parms[aPIPE].items ? 1 : 0);
177 /* Determine if we should also do a setpag based on -setpag switch */
178 dosetpag = (as->parms[aSETPAG].items ? 1 : 0);
180 if (as->parms[aTMP].items) {
184 cm_GetRootCellName(defaultCell);
187 /* Parse our arguments. */
189 if (as->parms[aCELL].items) {
191 * cell name explicitly mentioned; take it in if no other cell name
192 * has already been specified and if the name actually appears. If
193 * the given cell name differs from our own, we don't do a lookup.
195 foundExplicitCell = 1;
196 strncpy (realm, as->parms[aCELL].items->data, sizeof(realm));
199 if (as->parms[aSERVERS].items) {
200 fprintf (stderr, "SERVERS option not available.\n");
203 if (as->parms[aPRINCIPAL].items) {
204 ka_ParseLoginName (as->parms[aPRINCIPAL].items->data,
205 name, instance, cell);
206 if (strlen (instance) > 0)
209 "Non-null instance (%s) may cause strange behavior.\n",
212 if (strlen(cell) > 0) {
213 if (foundExplicitCell) {
216 "%s: May not specify an explicit cell twice.\n", rn);
220 foundExplicitCell = 1;
221 strncpy (realm, cell, sizeof(realm));
224 /* No explicit name provided. */
225 DWORD size = GetEnvironmentVariable("USERNAME", name, sizeof(name) - 1);
226 if (size <= 0 || size >= sizeof(name)) {
227 size = sizeof(name) - 1;
228 if (!GetUserName(name, &size)) {
229 KLOGEXIT( KABADARGUMENT );
234 if (as->parms[aPASSWORD].items) {
236 * Current argument is the desired password string. Remember it in
237 * our local buffer, and zero out the argument string - anyone can
238 * see it there with ps!
241 strncpy (passwd, as->parms[aPASSWORD].items->data, sizeof(passwd));
242 memset (as->parms[aPASSWORD].items->data, 0,
243 strlen(as->parms[aPASSWORD].items->data));
246 if (as->parms[aLIFETIME].items) {
247 char *life = as->parms[aLIFETIME].items->data;
248 char *sp; /* string ptr to rest of life */
249 lifetime = 3600*strtol (life, &sp, 0); /* hours */
252 if (!Silent) fprintf (stderr, "%s: translating '%s' to lifetime failed\n",
254 return KABADARGUMENT;
257 life = sp+1; /* skip the colon */
258 lifetime += 60*strtol (life, &sp, 0); /* minutes */
259 if (sp == life) goto bad_lifetime;
262 lifetime += strtol (life, &sp, 0); /* seconds */
263 if (sp == life) goto bad_lifetime;
264 if (*sp) goto bad_lifetime;
265 } else if (*sp) goto bad_lifetime;
266 } else if (*sp) goto bad_lifetime;
267 if (lifetime > MAXKTCTICKETLIFETIME) {
270 "%s: a lifetime of %.2f hours is too long, must be less than %d.\n",
271 rn, (double)lifetime/3600.0, MAXKTCTICKETLIFETIME/3600);
272 KLOGEXIT( KABADARGUMENT );
276 if (!foundExplicitCell) strcpy (realm, defaultCell);
278 /* Get the password if it wasn't provided. */
279 if (!foundPassword) {
281 strncpy(passwd, getpipepass(), sizeof(passwd));
284 if (read_pw_string(passwd, sizeof(passwd)))
285 reason = "can't read password from terminal";
286 else if (strlen(passwd) == 0)
287 reason = "zero length password is illegal";
291 fprintf (stderr, "Unable to login because %s.\n", reason);
292 KLOGEXIT( KABADARGUMENT );
297 code = ka_UserAuthenticateGeneral (KA_USERAUTH_VERSION,
298 name, instance, realm, passwd, lifetime,
299 &password_expires, 0, &reason);
300 memset (passwd, 0, sizeof(passwd));
304 "Unable to authenticate to AFS because %s.\n", reason);
309 #ifndef AFS_KERBEROS_ENV
310 if (writeTicketFile) {
311 code = krb_write_ticket_file (realm);
314 com_err (rn, code, "writing Kerberos ticket file");
315 else fprintf (stderr, "Wrote ticket file to /tmp\n");
321 if (password_expires >= 0) {
322 printf ("password expires at %ld\n", password_expires);
324 #endif /* DEBUGEXPIRES */