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
14 #include <afsconfig.h>
15 #include <afs/param.h>
20 #include <sys/types.h>
27 #include <sys/ioctl.h>
32 #include <afs/afsutil.h>
33 #include <afs/sys_prototypes.h>
38 29 Oct 1992 Patch GetTokens to print something reasonable when there are no tokens.
42 /* this is a structure used to communicate with the afs cache mgr, but is
43 * otherwise irrelevant, or worse.
49 afs_int32 BeginTimestamp
;
50 afs_int32 EndTimestamp
;
55 SetSysname(afs_int32 ahost
, afs_int32 auid
, char *sysname
)
59 char space
[1200], *tp
;
60 struct ViceIoctl blob
;
63 /* otherwise we've got the token, now prepare to build the pioctl args */
66 pheader
[2] = 0; /* group low */
67 pheader
[3] = 0; /* group high */
68 pheader
[4] = 38 /*VIOC_AFS_SYSNAME */ ; /* sysname pioctl index */
69 pheader
[5] = 1; /* NFS protocol exporter # */
72 memcpy(space
, pheader
, sizeof(pheader
));
73 tp
= space
+ sizeof(pheader
);
75 /* finally setup the pioctl call's parameters */
76 blob
.in_size
= sizeof(pheader
);
80 memcpy(tp
, &setp
, sizeof(afs_int32
));
81 tp
+= sizeof(afs_int32
);
83 blob
.in_size
+= sizeof(afs_int32
) + strlen(sysname
) + 1;
84 tp
+= strlen(sysname
);
86 code
= pioctl(NULL
, _VICEIOCTL(99), &blob
, 0);
95 GetTokens(afs_int32 ahost
, afs_int32 auid
)
102 char *stp
; /* secret token ptr */
103 struct ClearToken ct
;
105 afs_int32 temp
, gotit
= 0;
106 int maxLen
; /* biggest ticket we can copy */
107 int tktLen
; /* server ticket length */
108 time_t tokenExpireTime
;
109 char UserName
[MAXKTCNAMELEN
+ MAXKTCNAMELEN
];
110 struct ktc_token token
;
111 struct ktc_principal clientName
;
115 current_time
= time(0);
117 /* otherwise we've got the token, now prepare to build the pioctl args */
120 pheader
[2] = 0; /* group low */
121 pheader
[3] = 0; /* group high */
122 pheader
[4] = 8; /* gettoken pioctl index */
123 pheader
[5] = 1; /* NFS protocol exporter # */
125 for (index
= 0; index
< 200; index
++) { /* sanity check in case pioctl fails */
126 code
= ktc_ListTokens(index
, &newIndex
, &clientName
);
128 if (code
== KTC_NOENT
) {
131 printf("knfs: there are no tokens here.\n");
134 break; /* done, but failed */
136 if (strcmp(clientName
.name
, "afs") != 0)
137 continue; /* wrong ticket service */
140 memcpy(tbuffer
, pheader
, sizeof(pheader
));
141 tp
= tbuffer
+ sizeof(pheader
);
142 memcpy(tp
, &index
, sizeof(afs_int32
));
143 tp
+= sizeof(afs_int32
);
145 iob
.in_size
= sizeof(afs_int32
) + sizeof(pheader
);
147 iob
.out_size
= sizeof(tbuffer
);
148 code
= pioctl(NULL
, _VICEIOCTL(99), &iob
, 0);
149 if (code
< 0 && errno
== EDOM
)
151 else if (code
== 0) {
152 /* check to see if this is the right cell/realm */
154 memcpy(&temp
, tp
, sizeof(afs_int32
)); /* get size of secret token */
155 tktLen
= temp
; /* remember size of ticket */
156 tp
+= sizeof(afs_int32
);
157 stp
= tp
; /* remember where ticket is, for later */
158 tp
+= temp
; /* skip ticket for now */
159 memcpy(&temp
, tp
, sizeof(afs_int32
)); /* get size of clear token */
160 if (temp
!= sizeof(struct ClearToken
))
162 tp
+= sizeof(afs_int32
); /* skip length */
163 memcpy(&ct
, tp
, temp
); /* copy token for later use */
164 tp
+= temp
; /* skip clear token itself */
165 tp
+= sizeof(afs_int32
); /* skip primary flag */
166 /* tp now points to the cell name */
167 if (strcmp(tp
, clientName
.cell
) == 0) {
168 /* closing in now, we've got the right cell */
171 sizeof(token
) - sizeof(struct ktc_token
) +
173 if (tktLen
< 0 || tktLen
> maxLen
)
175 memcpy(token
.ticket
, stp
, tktLen
);
176 token
.startTime
= ct
.BeginTimestamp
;
177 token
.endTime
= ct
.EndTimestamp
;
178 if (ct
.AuthHandle
== -1)
180 token
.kvno
= ct
.AuthHandle
;
181 memcpy(&token
.sessionKey
, ct
.HandShakeKey
,
182 sizeof(struct ktc_encryptionKey
));
183 token
.ticketLen
= tktLen
;
184 if ((token
.kvno
== 999) || /* old style bcrypt ticket */
185 (ct
.BeginTimestamp
&& /* new w/ prserver lookup */
186 (((ct
.EndTimestamp
- ct
.BeginTimestamp
) & 1) == 1))) {
187 sprintf(clientName
.name
, "AFS ID %d", ct
.ViceId
);
188 clientName
.instance
[0] = 0;
190 sprintf(clientName
.name
, "Unix UID %d", ct
.ViceId
);
191 clientName
.instance
[0] = 0;
193 strlcpy(clientName
.cell
, tp
, sizeof(clientName
.cell
));
195 tokenExpireTime
= token
.endTime
;
196 strlcpy(UserName
, clientName
.name
, sizeof(UserName
));
197 if (clientName
.instance
[0] != 0) {
198 strlcat(UserName
, ".", sizeof(UserName
));
199 strlcat(UserName
, clientName
.instance
, sizeof(UserName
));
201 if (UserName
[0] == 0)
203 else if (strncmp(UserName
, "AFS ID", 6) == 0) {
204 printf("User's (%s) tokens", UserName
);
205 } else if (strncmp(UserName
, "Unix UID", 8) == 0) {
208 printf("User %s's tokens", UserName
);
209 printf(" for %s%s%s@%s ", clientName
.name
,
210 clientName
.instance
[0] ? "." : "", clientName
.instance
,
212 if (tokenExpireTime
<= current_time
)
213 printf("[>> Expired <<]\n");
215 expireString
= ctime(&tokenExpireTime
);
216 expireString
+= 4; /*Move past the day of week */
217 expireString
[12] = '\0';
218 printf("[Expires %s]\n", expireString
);
229 NFSUnlog(afs_int32 ahost
, afs_int32 auid
)
232 afs_int32 pheader
[6];
234 struct ViceIoctl blob
;
236 /* otherwise we've got the token, now prepare to build the pioctl args */
239 pheader
[2] = 0; /* group low */
240 pheader
[3] = 0; /* group high */
241 pheader
[4] = 9; /* unlog pioctl index */
242 pheader
[5] = 1; /* NFS protocol exporter # */
245 memcpy(space
, pheader
, sizeof(pheader
));
247 /* finally setup the pioctl call's parameters */
248 blob
.in_size
= sizeof(pheader
);
252 code
= pioctl(NULL
, _VICEIOCTL(99), &blob
, 0);
259 /* Copy the AFS service token into the kernel for a particular host and user */
261 NFSCopyToken(afs_int32 ahost
, afs_int32 auid
)
263 struct ktc_principal client
, server
;
264 struct ktc_token theTicket
;
266 afs_int32 pheader
[6];
268 struct ClearToken ct
;
269 afs_int32 index
, newIndex
;
270 afs_int32 temp
; /* for bcopy */
272 struct ViceIoctl blob
;
274 for (index
= 0;; index
= newIndex
) {
275 code
= ktc_ListTokens(index
, &newIndex
, &server
);
277 if (code
== KTC_NOENT
) {
281 break; /* done, but failed */
283 if (strcmp(server
.name
, "afs") != 0)
284 continue; /* wrong ticket service */
285 code
= ktc_GetToken(&server
, &theTicket
, sizeof(theTicket
), &client
);
289 /* otherwise we've got the token, now prepare to build the pioctl args */
292 pheader
[2] = 0; /* group low */
293 pheader
[3] = 0; /* group high */
294 pheader
[4] = 3; /* set token pioctl index */
295 pheader
[5] = 1; /* NFS protocol exporter # */
297 /* copy in the header */
298 memcpy(space
, pheader
, sizeof(pheader
));
299 tp
= space
+ sizeof(pheader
);
300 /* copy in the size of the encrypted part */
301 memcpy(tp
, &theTicket
.ticketLen
, sizeof(afs_int32
));
302 tp
+= sizeof(afs_int32
);
303 /* copy in the ticket itself */
304 memcpy(tp
, theTicket
.ticket
, theTicket
.ticketLen
);
305 tp
+= theTicket
.ticketLen
;
306 /* copy in "clear token"'s size */
307 temp
= sizeof(struct ClearToken
);
308 memcpy(tp
, &temp
, sizeof(afs_int32
));
309 tp
+= sizeof(afs_int32
);
310 /* create the clear token and copy *it* in */
311 ct
.AuthHandle
= theTicket
.kvno
; /* where we hide the key version # */
312 memcpy(ct
.HandShakeKey
, &theTicket
.sessionKey
,
313 sizeof(ct
.HandShakeKey
));
316 ct
.BeginTimestamp
= theTicket
.startTime
;
317 ct
.EndTimestamp
= theTicket
.endTime
;
318 memcpy(tp
, &ct
, sizeof(ct
));
320 /* copy in obsolete primary flag */
322 memcpy(tp
, &temp
, sizeof(afs_int32
));
323 tp
+= sizeof(afs_int32
);
324 /* copy in cell name, null terminated */
325 strcpy(tp
, server
.cell
);
326 tp
+= strlen(server
.cell
) + 1;
328 /* finally setup the pioctl call's parameters */
329 blob
.in_size
= tp
- space
;
333 code
= pioctl(NULL
, _VICEIOCTL(99), &blob
, 0);
343 cmdproc(struct cmd_syndesc
*as
, void *arock
)
346 char *tp
, *sysname
= 0;
350 the
= (struct hostent
*)
351 hostutil_GetHostByName(tp
= as
->parms
[0].items
->data
);
353 printf("knfs: unknown host '%s'.\n", tp
);
356 memcpy(&addr
, the
->h_addr
, sizeof(afs_int32
));
358 if (as
->parms
[1].items
) {
359 code
= util_GetInt32(tp
= as
->parms
[1].items
->data
, &uid
);
361 printf("knfs: can't parse '%s' as a number (UID)\n", tp
);
365 uid
= -1; /* means wildcard: match any user on this host */
368 * If not "-id" is passed then we use the getuid() id, unless it's root
369 * that is doing it in which case we only authenticate as "system:anyuser"
370 * as it's appropriate for root. (The cm handles conversions from 0 to
377 if (as
->parms
[2].items
) {
378 sysname
= as
->parms
[2].items
->data
;
381 if (as
->parms
[4].items
) {
382 /* tokens specified */
383 code
= GetTokens(addr
, uid
);
387 ("knfs: Translator in 'passwd sync' mode; remote uid must be the same as local uid\n");
389 printf("knfs: failed to get tokens for uid %d (code %d)\n",
395 /* finally, parsing is done, make the call */
396 if (as
->parms
[3].items
) {
397 /* unlog specified */
398 code
= NFSUnlog(addr
, uid
);
402 ("knfs: Translator in 'passwd sync' mode; remote uid must be the same as local uid\n");
404 printf("knfs: failed to unlog (code %d)\n", code
);
407 code
= NFSCopyToken(addr
, uid
);
411 ("knfs: Translator in 'passwd sync' mode; remote uid must be the same as local uid\n");
413 printf("knfs: failed to copy tokens (code %d)\n", code
);
416 code
= SetSysname(addr
, uid
, sysname
);
418 printf("knfs: failed to set client's @sys to %s (code %d)\n",
426 #include "AFS_component_version_number.c"
429 main(int argc
, char **argv
)
431 struct cmd_syndesc
*ts
;
436 * The following signal action for AIX is necessary so that in case of a
437 * crash (i.e. core is generated) we can include the user's data section
438 * in the core dump. Unfortunately, by default, only a partial core is
439 * generated which, in many cases, isn't too useful.
441 struct sigaction nsa
;
443 sigemptyset(&nsa
.sa_mask
);
444 nsa
.sa_handler
= SIG_DFL
;
445 nsa
.sa_flags
= SA_FULLDUMP
;
446 sigaction(SIGABRT
, &nsa
, NULL
);
447 sigaction(SIGSEGV
, &nsa
, NULL
);
450 ts
= cmd_CreateSyntax(NULL
, cmdproc
, NULL
, "copy tickets for NFS");
451 cmd_AddParm(ts
, "-host", CMD_SINGLE
, CMD_REQUIRED
, "host name");
452 cmd_AddParm(ts
, "-id", CMD_SINGLE
, CMD_OPTIONAL
, "user ID (decimal)");
453 cmd_AddParm(ts
, "-sysname", CMD_SINGLE
, CMD_OPTIONAL
,
454 "host's '@sys' value");
455 cmd_AddParm(ts
, "-unlog", CMD_FLAG
, CMD_OPTIONAL
, "unlog remote user");
456 cmd_AddParm(ts
, "-tokens", CMD_FLAG
, CMD_OPTIONAL
,
457 "display all tokens for remote [host,id]");
459 code
= cmd_Dispatch(argc
, argv
);