Logo ROOT   6.16/01
Reference Guide
Krb5Auth.cxx
Go to the documentation of this file.
1// @(#)root/krb5auth:$Id$
2// Author: Johannes Muelmenstaedt 17/03/2002
3
4/*************************************************************************
5 * Copyright (C) 1995-2002, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/* Parts of this file are copied from the MIT krb5 distribution and
13 * are subject to the following license:
14 *
15 * Copyright 1990,1991 by the Massachusetts Institute of Technology.
16 * All Rights Reserved.
17 *
18 * Export of this software from the United States of America may
19 * require a specific license from the United States Government.
20 * It is the responsibility of any person or organization contemplating
21 * export to obtain such a license before exporting.
22 *
23 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
24 * distribute this software and its documentation for any purpose and
25 * without fee is hereby granted, provided that the above copyright
26 * notice appear in all copies and that both that copyright notice and
27 * this permission notice appear in supporting documentation, and that
28 * the name of M.I.T. not be used in advertising or publicity pertaining
29 * to distribution of the software without specific, written prior
30 * permission. Furthermore if you modify this software you must label
31 * your software as modified software and not distribute it in such a
32 * fashion that it might be confused with the original M.I.T. software.
33 * M.I.T. makes no representations about the suitability of
34 * this software for any purpose. It is provided "as is" without express
35 * or implied warranty.
36 *
37 */
38
39#include <errno.h>
40#include <signal.h>
41#include <string.h>
42#include <sys/socket.h>
43#include <netinet/in.h>
44#include <netdb.h>
45#include <time.h>
46
47#include "Krb5Auth.h"
48#include "TSocket.h"
49#include "TAuthenticate.h"
50#include "TDatime.h"
51#include "TROOT.h"
52#include "THostAuth.h"
53#include "TError.h"
54#include "TSystem.h"
55#include "TEnv.h"
56#include "NetErrors.h"
57#include "Getline.h"
58
59#if defined(R__KRB5_NEED_VCST_DEFINE)
60#define krb5_c_valid_cksumtype valid_cksumtype
61#endif
62#if defined(R__KRB5_NEED_VCST_PROTO)
63krb5_boolean krb5_c_valid_cksumtype(krb5_cksumtype ctype);
64#endif
65
67
68static Int_t Krb5InitCred(const char *clientPrincipal, Bool_t promptPrinc = kFALSE);
69static Int_t Krb5CheckCred(krb5_context, krb5_ccache, TString, TDatime &);
70static Int_t Krb5CheckSecCtx(const char *, TRootSecContext *);
71
72class TKrb5AuthInit {
73public:
75};
76static TKrb5AuthInit gKrb5authInit;
77
78class TKrb5CleanUp {
79public:
80 Bool_t fSignal;
81 krb5_context fContext;
82 krb5_ccache fCcdef;
83 krb5_principal fClient;
84 krb5_principal fServer;
85 krb5_auth_context fAuthContext;
86 krb5_ap_rep_enc_part *fRepRet;
87 char *fData;
88
89 TKrb5CleanUp() : fSignal(false), fContext(0), fCcdef(0), fClient(0),
90 fServer(0), fAuthContext(0), fRepRet(0), fData(0) {
91 }
92
93 ~TKrb5CleanUp() {
94 if (fSignal) gSystem->IgnoreSignal(kSigPipe, kFALSE);
95
96 if (fData) free(fData);
97 if (fRepRet) krb5_free_ap_rep_enc_part(fContext, fRepRet);
98
99 if (fAuthContext) krb5_auth_con_free(fContext, fAuthContext);
100
101 if (fServer) krb5_free_principal(fContext, fServer);
102 if (fClient) krb5_free_principal(fContext, fClient);
103
104
105 if (fCcdef) krb5_cc_close(fContext, fCcdef);
106 if (fContext) krb5_free_context(fContext);
107 }
108};
109
110
111////////////////////////////////////////////////////////////////////////////////
112/// Kerberos v5 authentication code. Returns 0 in case authentication
113/// failed, 1 in case of success and 2 in case remote does not support
114/// Kerberos5.
115/// Protocol 'version': 3 supports alternate username
116/// 2 supports negotiation and auth reuse
117/// 1 first kerberos implementation
118/// 0 no kerberos support (function should not be called)
119/// user is used to input the target username and return the name in the
120/// principal used
121
123 Int_t version)
124{
125
126 TKrb5CleanUp cleanup;
127
128 int retval;
129 int kind;
130 TSocket *sock = auth->GetSocket();
131
132 char answer[256];
133 int type;
134 Int_t nsen = 0, nrec = 0;
135
136 TString targetUser(user);
137 TString localUser;
138 // The default will be the one related to the logged user
140 if (u) {
141 localUser = u->fUser;
142 delete u;
143 } else
144 localUser = TAuthenticate::GetDefaultUser();
145 Bool_t promptPrinc = (targetUser != localUser);
146
147 // first check if protocol version supports kerberos, krb5 support
148 // was introduced in rootd version 6
149 // This checked in the calling rootines and the result is contained in
150 // the argument 'version'
151 if (version <= 0) return 2; // ... but you shouldn't have got here ...
152
153 // get a context
154 krb5_context context;
155 retval = krb5_init_context(&context);
156 cleanup.fContext = context;
157
158 if (retval) {
159 Error("Krb5Authenticate","failed <krb5_init_context>: %s\n",
160 error_message(retval));
161 return -1;
162 }
163
164 // ignore broken connection signal handling
166 cleanup.fSignal = kTRUE;
167
168 // get our credentials cache
169 krb5_ccache ccdef;
170 if (gDebug > 2) {
171 if (gSystem->Getenv("KRB5CCNAME"))
172 Info("Krb5Authenticate",
173 "Use credential file from $KRB5CCNAME: %s\n",
174 gSystem->Getenv("KRB5CCNAME"));
175 else
176 Info("Krb5Authenticate",
177 "Use default credential file ($KRB5CCNAME undefined)");
178 }
179 if ((retval = krb5_cc_default(context, &ccdef))) {
180 Error("Krb5Authenticate","failed <krb5_cc_default>: %s\n",
181 error_message(retval));
182 return -1;
183 }
184 cleanup.fCcdef = ccdef;
185
186 // get our principal from the cache
187 krb5_principal client;
189 Bool_t gotPrincipal = (principal.Length() > 0) ? kTRUE : kFALSE;
190 //
191 // if not defined or incomplete, complete with defaults;
192 // but only if interactive
193 if (!principal.Length() || !principal.Contains("@")) {
194 if (gDebug > 3)
195 Info("Krb5Authenticate",
196 "incomplete principal: complete using defaults");
197 krb5_principal default_princ;
198
199 if (!principal.Length()) {
200 // Try the default user
201 if ((retval = krb5_parse_name(context, localUser.Data(),
202 &default_princ))) {
203 Error("Krb5Authenticate","failed <krb5_parse_name>: %s\n",
204 error_message(retval));
205 }
206 } else {
207 // Try first the name specified
208 if ((retval = krb5_parse_name(context, principal.Data(),
209 &default_princ))) {
210 TString errmsg = TString(Form("First: %s",error_message(retval)));
211 // Try the default user in case of failure
212 if ((retval = krb5_parse_name(context, localUser.Data(),
213 &default_princ))) {
214 errmsg.Append(Form("- Second: %s",error_message(retval)));
215 Error("Krb5Authenticate","failed <krb5_parse_name>: %s\n",
216 errmsg.Data());
217 }
218 }
219 }
220 //
221 // If successful, we get the string principal
222 if (!retval) {
223 char *default_name;
224 if ((retval = krb5_unparse_name(context, default_princ, &default_name))) {
225 Error("Krb5Authenticate","failed <krb5_unparse_name>: %s\n",
226 error_message(retval));
227 } else {
228 principal = TString(default_name);
229 free(default_name);
230 }
231 krb5_free_principal(context, default_princ);
232 }
233 }
234 // Notify
235 if (gDebug > 3) {
236 if (gotPrincipal)
237 Info("Krb5Authenticate",
238 "user requested principal: %s", principal.Data());
239 else
240 Info("Krb5Authenticate",
241 "default principal: %s", principal.Data());
242 }
243
244 if ((retval = krb5_cc_get_principal(context, ccdef, &client))) {
245
246 if (isatty(0) && isatty(1)) {
247
248 if (gDebug > 1)
249 Info("Krb5Authenticate",
250 "valid credentials not found: try initializing (Principal: %s)",
251 principal.Data());
252 if (Krb5InitCred(principal, promptPrinc)) {
253 Error("Krb5Authenticate","error executing kinit");
254 return -1;
255 }
256 if ((retval = krb5_cc_get_principal(context, ccdef, &client))) {
257 Error("Krb5Authenticate","failed <krb5_cc_get_principal>: %s\n",
258 error_message(retval));
259 return -1;
260 }
261 } else {
262 Warning("Krb5Authenticate",
263 "not a tty: cannot prompt for credentials, returning failure");
264 return -1;
265 }
266 }
267
268 // If a principal was specified by the user, we must check that the
269 // principal for which we have a cached ticket is the one that we want
270 TString ticketPrincipal =
271 TString(Form("%.*s@%.*s",client->data->length, client->data->data,
272 client->realm.length, client->realm.data));
273 if (gotPrincipal) {
274
275 // If interactive require the ticket principal to be the same as the
276 // required or default one
277 if (isatty(0) && isatty(1) && principal != ticketPrincipal) {
278 if (gDebug > 3)
279 Info("Krb5Authenticate",
280 "got credentials for different principal %s - try"
281 " initialization credentials for principal: %s",
282 ticketPrincipal.Data(), principal.Data());
283 if (Krb5InitCred(principal)) {
284 Error("Krb5Authenticate","error executing kinit");
285 return -1;
286 }
287 if ((retval = krb5_cc_get_principal(context, ccdef, &client))) {
288 Error("Krb5Authenticate","failed <krb5_cc_get_principal>: %s\n",
289 error_message(retval));
290 return -1;
291 }
292 // This may have changed
293 ticketPrincipal =
294 TString(Form("%.*s@%.*s",client->data->length, client->data->data,
295 client->realm.length, client->realm.data));
296 }
297 }
298
299 cleanup.fClient = client;
300
301 TDatime expDate;
302 if (Krb5CheckCred(context, ccdef, ticketPrincipal, expDate) != 1) {
303
304 // If the ticket expired we tray to re-initialize it for the same
305 // principal, which may be different from the default
306
307 if (isatty(0) && isatty(1)) {
308
309 if (gDebug >2)
310 Info("Krb5Authenticate",
311 "credentials found have expired: try initializing"
312 " (Principal: %s)", ticketPrincipal.Data());
313 if (Krb5InitCred(ticketPrincipal)) {
314 Error("Krb5Authenticate","error executing kinit");
315 return -1;
316 }
317 if ((retval = krb5_cc_get_principal(context, ccdef, &client))) {
318 Error("Krb5Authenticate","failed <krb5_cc_get_principal>: %s\n",
319 error_message(retval));
320 return -1;
321 }
322 // Check credentials and get expiration time
323 if (Krb5CheckCred(context, ccdef, ticketPrincipal, expDate) != 1) {
324 Info("Krb5Authenticate",
325 "ticket re-initialization failed for principal %s",
326 ticketPrincipal.Data());
327 return -1;
328 }
329 } else {
330 Warning("Krb5Authenticate",
331 "not a tty: cannot prompt for credentials, returning failure");
332 return -1;
333 }
334 }
335 cleanup.fClient = client;
336
337 // At this point we know which is the principal we will be using
338 if (gDebug > 3)
339 Info("Krb5Authenticate",
340 "using valid ticket for principal: %s", ticketPrincipal.Data());
341
342 // Get a normal string for user
343 TString normUser(client->data->data, client->data->length);
344
345 if (gDebug > 3) {
346 Info("Krb5Authenticate", "cc_get_principal: client: %.*s %.*s",
347 client->data->length, client->data->data,
348 client->realm.length, client->realm.data);
349 }
350
351 Int_t reuse = 1, prompt = 0;
352 TString details;
353
354 if (version > 1) {
355
356 // Check ReUse
359
360 // Build auth details
361 details = Form("pt:%d ru:%d us:%s", prompt, reuse, ticketPrincipal.Data());
362
363 // Create Options string
364 int opt = reuse * kAUTH_REUSE_MSK +
366 TString options(Form("%d %d %s", opt, normUser.Length(), normUser.Data()));
367
368 // Now we are ready to send a request to the rootd/proofd daemons
369 // to check if we have already a valid security context and
370 // eventually to start a negotiation to get one ...
371 kind = kROOTD_KRB5;
372 retval = reuse;
373 int rc = 0;
374 if ((rc = auth->AuthExists(ticketPrincipal, TAuthenticate::kKrb5,
375 options, &kind, &retval, &Krb5CheckSecCtx)) == 1) {
376 // A valid authentication exists: we are done ...
377 return 1;
378 }
379 if (rc == -2) {
380 return rc;
381 }
382
383 if (kind == kROOTD_ERR) {
384 TString serv = "sockd";
385 if (strstr(auth->GetProtocol(),"root"))
386 serv = "rootd";
387 if (strstr(auth->GetProtocol(),"proof"))
388 serv = "proofd";
389 if (retval == kErrConnectionRefused) {
390 if (gDebug > 0)
391 Error("Krb5Authenticate",
392 "%s@%s does not accept connections from %s%s",
393 serv.Data(), auth->GetRemoteHost(),
394 auth->GetUser(), gSystem->HostName());
395 return -2;
396 } else if (retval == kErrNotAllowed) {
397 if (gDebug > 0)
398 Error("Krb5Authenticate",
399 "%s@%s does not accept %s authentication from %s@%s",
400 serv.Data(), auth->GetRemoteHost(),
402 auth->GetUser(), gSystem->HostName());
403 } else
404 TAuthenticate::AuthError("Krb5Authenticate", retval);
405 return 0;
406 }
407
408 } else {
409
410 nsen = sock->Send(kROOTD_KRB5);
411 if (nsen <= 0) {
412 Error("Krb5Authenticate","Sending kROOTD_KRB5");
413 return 0;
414 }
415 nrec = sock->Recv(retval, kind);
416 if (nrec <= 0) {
417 Error("Krb5Authenticate","Receiving kROOTD_KRB5");
418 return 0;
419 }
420
421 // retval == 0 when no Krb5 support compiled in remote rootd
422 if (retval == 0 || kind != kROOTD_KRB5)
423 return 2;
424 }
425
426 // ok, krb5 is supported
427 // ignore broken connection signal handling
429 cleanup.fSignal = kFALSE;
430
431 // test for CRC-32
432 if (!krb5_c_valid_cksumtype(CKSUMTYPE_CRC32)) {
433 Error("Krb5Authenticate","failed <krb5_c_valid_cksumtype>: %s\n",
434 error_message(KRB5_PROG_SUMTYPE_NOSUPP));
435 return 0;
436 }
437
438 // get service principal from service and host names --
439 // hard coding of service names avoids having the have these
440 // services in the local /etc/services file
441 TString service = TString("host");
442
443 TString serv_host(sock->GetInetAddress().GetHostName());
444 krb5_principal server;
445
446 if (gDebug > 3)
447 Info("Krb5Authenticate","serv_host: %s service: %s",
448 serv_host.Data(),service.Data());
449
450 if ((retval = krb5_sname_to_principal(context, serv_host.Data(),
451 service.Data(), KRB5_NT_SRV_HST, &server))) {
452
453 Error("Krb5Authenticate","failed <krb5_sname_to_principal>: %s\n",
454 error_message(retval));
455 return 0;
456 }
457 cleanup.fServer = server;
458
459 if (gDebug > 3) {
460 Info("Krb5Authenticate","sname_to_principal: server: %.*s %.*s",
461 server->data->length, server->data->data,
462 server->realm.length, server->realm.data);
463 }
464
465 // authenticate
466 krb5_auth_context auth_context = 0;
467 int sockd = sock->GetDescriptor();
468 char proto_version[100] = "krootd_v_1";
469 krb5_data cksum_data;
470 cksum_data.data = (char *)serv_host.Data(); // eeew yuck
471 cksum_data.length = serv_host.Length();
472 krb5_error *err_ret;
473 krb5_ap_rep_enc_part *rep_ret;
474
475 retval = krb5_auth_con_init(context, &auth_context);
476 if (retval)
477 Error("Krb5Authenticate","failed auth_con_init: %s\n",
478 error_message(retval));
479 cleanup.fAuthContext = auth_context;
480
481 retval = krb5_auth_con_setflags(context, auth_context,
482 KRB5_AUTH_CONTEXT_RET_TIME);
483 if (retval) Error("Krb5Authenticate","failed auth_con_setflags: %s\n",
484 error_message(retval));
485
486 if (gDebug > 1)
487 Info("Krb5Authenticate",
488 "Sending kerberos authentication to %s",
489 serv_host.Data());
490
491 retval = krb5_sendauth(context, &auth_context, (krb5_pointer)&sockd,
492 proto_version, client, server,
493 AP_OPTS_MUTUAL_REQUIRED,
494 &cksum_data,
495 0, // not rolling our own creds, using ccache
496 ccdef, &err_ret, &rep_ret, 0); // ugh!
497
498 // handle the reply (this is a verbatim copy from the kerberos
499 // sample client source)
500 if (retval && retval != KRB5_SENDAUTH_REJECTED) {
501 Error("Krb5Authenticate","failed <krb5_sendauth>: %s\n",
502 error_message(retval));
503 return 0;
504 }
505 if (retval == KRB5_SENDAUTH_REJECTED) {
506 // got an error
507 Error("Krb5Authenticate", "sendauth rejected, error reply "
508 "is:\n\t\"%.*s\"",
509 err_ret->text.length, err_ret->text.data);
510 return 0;
511 } else if (!rep_ret) {
512 // no reply
513 return 0;
514 }
515 cleanup.fRepRet = rep_ret;
516
517 if (version > 2) {
518
519 // Send the targetUser name
520
521 if (gDebug > 0)
522 Info("Krb5Authenticate","client is %s target is %s",
523 normUser.Data(),targetUser.Data());
524 nsen = sock->Send(targetUser.Data(), kROOTD_KRB5);
525 if (nsen <= 0) {
526 Error("Krb5Authenticate","Sending <targetUser>");
527 return 0;
528 }
529
530 // If PROOF, send credentials
531 if (sock->GetServType() == TSocket::kPROOFD || version < 4) {
532
533 krb5_data outdata;
534 outdata.data = 0;
535
536 retval = krb5_auth_con_genaddrs(context, auth_context,
537 sockd, KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR);
538
539 if (retval) {
540 Error("Krb5Authenticate","failed auth_con_genaddrs is: %s\n",
541 error_message(retval));
542 }
543
544 retval = krb5_fwd_tgt_creds(context, auth_context, 0 /*host*/,
545 client, server, ccdef, true,
546 &outdata);
547 if (retval) {
548 Error("Krb5Authenticate","fwd_tgt_creds failed: %s\n",
549 error_message(retval));
550 return 0;
551 }
552
553 cleanup.fData = outdata.data;
554
555 if (gDebug > 3)
556 Info("Krb5Authenticate",
557 "Sending kerberos forward ticket to %s %p %d [%d,%d,%d,...]",
558 serv_host.Data(), outdata.data, outdata.length,
559 outdata.data[0], outdata.data[1], outdata.data[2]);
560
561 // Send length first
562 char buflen[20];
563 snprintf(buflen, 20, "%d", outdata.length);
564 nsen = sock->Send(buflen, kROOTD_KRB5);
565 if (nsen <= 0) {
566 Error("Krb5Authenticate","Sending <buflen>");
567 return 0;
568 }
569
570 // Send Key. second ...
571 nsen = sock->SendRaw(outdata.data, outdata.length);
572 if (nsen <= 0) {
573 Error("Krb5Authenticate","Sending <Key>");
574 return 0;
575 }
576
577 if (gDebug>3)
578 Info("Krb5Authenticate",
579 "For kerberos forward ticket sent %d bytes (expected %d)",
580 nsen, outdata.length);
581 }
582 }
583
584 // restore attention to broken connection signal handling
586
587 // returns user@realm
589 nrec = sock->Recv(answer, 100, type);
590
591 if (type == kROOTD_ERR) {
592 TAuthenticate::AuthError("Krb5Authenticate", kErrNoHome);
593 return 0;
594 }
595
596 if (nrec <= 0) {
597 Error("Krb5Authenticate","Receiving <user@realm>");
598 return 0;
599 }
600 if (gDebug > 3)
601 Info("Krb5Auth","%s",answer);
602
603 if (version > 1) {
604
605 // Receive key request
606 nrec = sock->Recv(retval, type);
607 if (nrec <= 0) {
608 Error("Krb5Authenticate","Receiving <key request>");
609 return 0;
610 }
611
612 Int_t rsaKey = 0;
613 if (reuse == 1) {
614
615 if (type != kROOTD_RSAKEY || retval < 1 || retval > 2 ) {
616 Error("Krb5Auth",
617 "problems recvn RSA key flag: got message %d, flag: %d",
618 type, rsaKey);
619 return 0;
620 }
621 rsaKey = retval - 1;
622
623 // Send the key securely
625
626 // get length of user + offset string
627 nrec = sock->Recv(retval, type);
628 if (nrec <= 0) {
629 Error("Krb5Authenticate","Receiving <length of user+offset string>");
630 return 0;
631 }
632 }
633
634 if (type != kROOTD_KRB5 || retval < 1) {
635 Warning("Krb5Auth",
636 "problems recvn (user,offset) length (%d:%d bytes:%d)",
637 type, retval, nrec);
638 return 0;
639 }
640 char *rfrm = new char[retval+1];
641 nrec = sock->Recv(rfrm,retval+1, type); // receive user,offset) info
642 if (nrec <= 0) {
643 Error("Krb5Authenticate","Receiving <user+offset string>");
644 delete[] rfrm;
645 return 0;
646 }
647
648 // Parse answer
649 char lUser[128];
650 int offset = -1;
651 sscanf(rfrm,"%127s %d", lUser, &offset);
652 // Save username
653 user = lUser;
654
655 // Receive token
656 char *token = 0;
657 if (reuse == 1 && offset > -1) {
658 if (TAuthenticate::SecureRecv(sock, 1, rsaKey, &token) == -1) {
659 Warning("Krb5Auth",
660 "problems secure-receiving token - may result in corrupted token");
661 }
662 if (gDebug > 3)
663 Info("Krb5Auth","received from server: token: '%s' ", token);
664 } else {
665 token = StrDup("");
666 }
667
668 // Create SecContext object
669 TRootSecContext *ctx =
670 auth->GetHostAuth()->CreateSecContext((const char *)lUser,
671 auth->GetRemoteHost(), (Int_t)TAuthenticate::kKrb5, offset,
672 details, token, expDate, 0, rsaKey);
673 // Transmit it to TAuthenticate
674 auth->SetSecContext(ctx);
675
676 det = details;
677 if (token) delete[] token;
678 } else {
679 nrec = sock->Recv(answer, 100, type); // returns user
680 if (nrec <= 0) {
681 Error("Krb5Authenticate","Receiving <user string>");
682 return 0;
683 }
684 user = answer;
685
686 // Get a SecContext for the record and avoid problems
687 // with fSecContext undefined in TAuthenticate
688 TRootSecContext *ctx =
689 auth->GetHostAuth()->CreateSecContext((const char *)user,
691 details, 0);
692 // Transmit it to TAuthenticate
693 auth->SetSecContext(ctx);
694 }
695
696 // Receive auth from remote login function
697 int authok = 0;
698 nrec = sock->Recv(authok, kind);
699 if (nrec <= 0) {
700 Error("Krb5Authenticate", "Receiving <Auth flag>");
701 return 0;
702 }
703
704 if (authok && kind == kROOTD_AUTH)
705 return 1;
706 return 0;
707}
708
709////////////////////////////////////////////////////////////////////////////////
710/// Checks if there are valid credentials in the cache.
711/// If not, tries to initialise them.
712
713Int_t Krb5InitCred(const char *clientPrincipal, Bool_t promptPrinc)
714{
715 if (gDebug > 2)
716 Info("Krb5InitCred","enter: %s", clientPrincipal);
717
718 // Check if the user wants to be prompt about principal
719 TString principal = TString(clientPrincipal);
720 if (TAuthenticate::GetPromptUser() || promptPrinc) {
721 const char *usr = Getline(Form("Principal (%s): ", principal.Data()));
722 if (usr[0]) {
723 TString usrs(usr);
724 usrs.Remove(usrs.Length() - 1); // get rid of \n
725 if (!usrs.IsNull())
726 principal = usrs;
727 }
728 }
729
730 // Prepare command
731 TString cmd;
732
733 if (strlen(R__KRB5INIT) <= 0)
734 cmd = Form("/usr/kerberos/bin/kinit -f %s", principal.Data());
735 else
736 cmd = Form("%s -f %s",R__KRB5INIT, principal.Data());
737
738 if (gDebug > 2)
739 Info("Krb5InitCred","executing: %s", cmd.Data());
740 Int_t rc = gSystem->Exec(cmd);
741 if (rc)
742 if (gDebug > 0)
743 Info("Krb5InitCred", "error: return code: %d", rc);
744 return rc;
745}
746
747////////////////////////////////////////////////////////////////////////////////
748/// Checks if there are valid credentials.
749
750Int_t Krb5CheckCred(krb5_context kCont, krb5_ccache Cc,
751 TString principal, TDatime &expDate)
752{
753 Int_t retval;
754 Int_t now = time(0);
755 Int_t valid = -1;
756
757 TString pdata = principal;
758 TString prealm = principal;
759 pdata.Resize(pdata.Index("@"));
760 prealm.Remove(0,prealm.Index("@")+1);
761 if (gDebug > 2)
762 Info("Krb5CheckCred","enter: principal '%s'", principal.Data());
763
764 // Init to now
765 expDate = TDatime();
766
767 krb5_cc_cursor cur;
768 if ((retval = krb5_cc_start_seq_get(kCont, Cc, &cur))) {
769 if (gDebug > 2)
770 Error("Krb5Authenticate","failed <krb5_cc_start_seq_get>: %s\n",
771 error_message(retval));
772 return 0;
773 }
774
775 krb5_creds creds;
776 while (!(retval = krb5_cc_next_cred(kCont, Cc, &cur, &creds)) && valid == -1) {
777
778 if (gDebug > 3) {
779 Info("Krb5CheckCred","creds.server->length: %d",
780 creds.server->length);
781 Info("Krb5CheckCred","Realms data: '%.*s' '%s'",
782 creds.server->realm.length, creds.server->realm.data,
783 prealm.Data());
784 Info("Krb5CheckCred","Srv data[0]: '%.*s' ",
785 creds.server->data[0].length, creds.server->data[0].data);
786 Info("Krb5CheckCred","Data data: '%.*s' '%s'",
787 creds.server->data[1].length, creds.server->data[1].data,
788 prealm.Data());
789 Info("Krb5CheckCred","Endtime: %d ", creds.times.endtime);
790 }
791
792 if (creds.server->length == 2 &&
793 !strncmp(creds.server->realm.data,
794 prealm.Data(),creds.server->realm.length) &&
795 !strncmp((char *)creds.server->data[0].data,
796 "krbtgt",creds.server->data[0].length) &&
797 !strncmp((char *)creds.server->data[1].data,
798 prealm.Data(),creds.server->data[1].length)) {
799 // Check expiration time
800 valid = (creds.times.endtime >= now) ? 1 : 0;
801 // Return expiration time
802 expDate.Set(creds.times.endtime);
803 }
804 krb5_free_cred_contents(kCont, &creds);
805 }
806 return valid;
807}
808
809////////////////////////////////////////////////////////////////////////////////
810/// Krb5 version of CheckSecCtx to be passed to TAuthenticate::AuthExists
811/// Check if principal is matches the one used to instantiate Ctx
812/// Returns: 1 if ok, 0 if not
813/// Deactivates Ctx is not valid
814
816{
817 Int_t rc = 0;
818
819 if (ctx->IsActive()) {
820 if (strstr(ctx->GetID(), principal))
821 rc = 1;
822 }
823 return rc;
824}
const Int_t kAUTH_REUSE_MSK
Definition: AuthConst.h:28
const Int_t kAUTH_RSATY_MSK
Definition: AuthConst.h:31
static Int_t Krb5InitCred(const char *clientPrincipal, Bool_t promptPrinc=kFALSE)
Checks if there are valid credentials in the cache.
Definition: Krb5Auth.cxx:713
Int_t Krb5Authenticate(TAuthenticate *, TString &, TString &, Int_t)
Kerberos v5 authentication code.
Definition: Krb5Auth.cxx:122
static TKrb5AuthInit gKrb5authInit
Definition: Krb5Auth.cxx:76
static Int_t Krb5CheckSecCtx(const char *, TRootSecContext *)
Krb5 version of CheckSecCtx to be passed to TAuthenticate::AuthExists Check if principal is matches t...
Definition: Krb5Auth.cxx:815
static Int_t Krb5CheckCred(krb5_context, krb5_ccache, TString, TDatime &)
Checks if there are valid credentials.
Definition: Krb5Auth.cxx:750
@ kROOTD_RSAKEY
Definition: MessageTypes.h:140
@ kMESS_STRING
Definition: MessageTypes.h:34
@ kROOTD_KRB5
Definition: MessageTypes.h:132
@ kROOTD_AUTH
Definition: MessageTypes.h:104
@ kROOTD_ERR
Definition: MessageTypes.h:113
@ kErrNoHome
Definition: NetErrors.h:43
@ kErrNotAllowed
Definition: NetErrors.h:49
@ kErrConnectionRefused
Definition: NetErrors.h:50
int Int_t
Definition: RtypesCore.h:41
const Bool_t kFALSE
Definition: RtypesCore.h:88
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kTRUE
Definition: RtypesCore.h:87
R__EXTERN Int_t gDebug
Definition: Rtypes.h:90
void Info(const char *location, const char *msgfmt,...)
void Error(const char *location, const char *msgfmt,...)
void Warning(const char *location, const char *msgfmt,...)
int type
Definition: TGX11.cxx:120
char * Form(const char *fmt,...)
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2465
@ kSigPipe
R__EXTERN TSystem * gSystem
Definition: TSystem.h:540
#define free
Definition: civetweb.c:1539
#define snprintf
Definition: civetweb.c:1540
const char * GetProtocol() const
void SetSecContext(TRootSecContext *ctx)
static const char * GetDefaultUser()
Static method returning the default user information.
static Bool_t GetPromptUser()
Static method returning the prompt user settings.
const char * GetRemoteHost() const
static Int_t SecureRecv(TSocket *Socket, Int_t dec, Int_t KeyType, char **Out)
Receive str from sock and decode it using key indicated by key type Return number of received bytes o...
static const char * GetKrb5Principal()
Static method returning the principal to be used to init Krb5 tickets.
TSocket * GetSocket() const
THostAuth * GetHostAuth() const
static void SetKrb5AuthHook(Krb5Auth_t func)
Set kerberos5 authorization function.
const char * GetUser() const
static Int_t SendRSAPublicKey(TSocket *Socket, Int_t key=0)
Receives server RSA Public key Sends local RSA public key encoded.
Int_t GetRSAKeyType() const
Int_t AuthExists(TString User, Int_t method, const char *Options, Int_t *Message, Int_t *Rflag, CheckSecCtx_t funcheck)
Check if we have a valid established sec context in memory Retrieves relevant info and negotiates wit...
static void AuthError(const char *where, Int_t error)
Print error string depending on error code.
static const char * GetAuthMethod(Int_t idx)
Static method returning the method corresponding to idx.
static Bool_t GetAuthReUse()
Static method returning the authentication reuse settings.
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition: TDatime.h:37
void Set()
Set Date/Time to current time as reported by the system.
Definition: TDatime.cxx:288
TRootSecContext * CreateSecContext(const char *user, const char *host, Int_t meth, Int_t offset, const char *details, const char *token, TDatime expdate=kROOTTZERO, void *ctx=0, Int_t key=-1)
Create a Security context and add it to local list Return pointer to it to be stored in TAuthenticate...
Definition: THostAuth.cxx:723
const char * GetHostName() const
Definition: TInetAddress.h:71
Bool_t IsActive() const
Check remote OffSet and expiring Date.
const char * GetID() const
Definition: TSecContext.h:76
virtual Int_t Recv(TMessage *&mess)
Receive a TMessage object.
Definition: TSocket.cxx:817
TInetAddress GetInetAddress() const
Definition: TSocket.h:133
virtual Int_t SendRaw(const void *buffer, Int_t length, ESendRecvOptions opt=kDefault)
Send a raw buffer of specified length.
Definition: TSocket.cxx:620
@ kPROOFD
Definition: TSocket.h:72
virtual Int_t GetDescriptor() const
Definition: TSocket.h:132
Int_t GetServType() const
Definition: TSocket.h:137
virtual Int_t Send(const TMessage &mess)
Send a TMessage object.
Definition: TSocket.cxx:522
Basic string class.
Definition: TString.h:131
Ssiz_t Length() const
Definition: TString.h:405
const char * Data() const
Definition: TString.h:364
void Resize(Ssiz_t n)
Resize the string. Truncate or add blanks as necessary.
Definition: TString.cxx:1070
Bool_t IsNull() const
Definition: TString.h:402
TString & Remove(Ssiz_t pos)
Definition: TString.h:668
TString & Append(const char *cs)
Definition: TString.h:559
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1652
virtual Int_t Exec(const char *shellcmd)
Execute a command.
Definition: TSystem.cxx:662
virtual void IgnoreSignal(ESignals sig, Bool_t ignore=kTRUE)
If ignore is true ignore the specified signal, else restore previous behaviour.
Definition: TSystem.cxx:602
virtual const char * HostName()
Return the system's host name.
Definition: TSystem.cxx:312
virtual UserGroup_t * GetUserInfo(Int_t uid)
Returns all user info in the UserGroup_t structure.
Definition: TSystem.cxx:1588
TString fUser
Definition: TSystem.h:142