42 #include <sys/socket.h>
43 #include <netinet/in.h>
59 #if defined(R__KRB5_NEED_VCST_DEFINE)
60 #define krb5_c_valid_cksumtype valid_cksumtype
62 #if defined(R__KRB5_NEED_VCST_PROTO)
63 krb5_boolean krb5_c_valid_cksumtype(krb5_cksumtype ctype);
81 krb5_context fContext;
83 krb5_principal fClient;
84 krb5_principal fServer;
85 krb5_auth_context fAuthContext;
86 krb5_ap_rep_enc_part *fRepRet;
89 TKrb5CleanUp() : fSignal(
false), fContext(0), fCcdef(0), fClient(0),
90 fServer(0), fAuthContext(0), fRepRet(0), fData(0) {
96 if (fData)
free(fData);
97 if (fRepRet) krb5_free_ap_rep_enc_part(fContext, fRepRet);
99 if (fAuthContext) krb5_auth_con_free(fContext, fAuthContext);
101 if (fServer) krb5_free_principal(fContext, fServer);
102 if (fClient) krb5_free_principal(fContext, fClient);
105 if (fCcdef) krb5_cc_close(fContext, fCcdef);
106 if (fContext) krb5_free_context(fContext);
134 Int_t nsen = 0, nrec = 0;
141 localUser = u->
fUser;
145 Bool_t promptPrinc = (targetUser != localUser);
151 if (version <= 0)
return 2;
154 krb5_context context;
155 retval = krb5_init_context(&context);
156 cleanup.fContext = context;
159 Error(
"Krb5Authenticate",
"failed <krb5_init_context>: %s\n",
160 error_message(retval));
166 cleanup.fSignal =
kTRUE;
172 Info(
"Krb5Authenticate",
173 "Use credential file from $KRB5CCNAME: %s\n",
176 Info(
"Krb5Authenticate",
177 "Use default credential file ($KRB5CCNAME undefined)");
179 if ((retval = krb5_cc_default(context, &ccdef))) {
180 Error(
"Krb5Authenticate",
"failed <krb5_cc_default>: %s\n",
181 error_message(retval));
184 cleanup.fCcdef = ccdef;
187 krb5_principal client;
195 Info(
"Krb5Authenticate",
196 "incomplete principal: complete using defaults");
197 krb5_principal default_princ;
199 if (!principal.
Length()) {
201 if ((retval = krb5_parse_name(context, localUser.
Data(),
203 Error(
"Krb5Authenticate",
"failed <krb5_parse_name>: %s\n",
204 error_message(retval));
208 if ((retval = krb5_parse_name(context, principal.
Data(),
212 if ((retval = krb5_parse_name(context, localUser.
Data(),
214 errmsg.
Append(
Form(
"- Second: %s",error_message(retval)));
215 Error(
"Krb5Authenticate",
"failed <krb5_parse_name>: %s\n",
224 if ((retval = krb5_unparse_name(context, default_princ, &default_name))) {
225 Error(
"Krb5Authenticate",
"failed <krb5_unparse_name>: %s\n",
226 error_message(retval));
228 principal =
TString(default_name);
231 krb5_free_principal(context, default_princ);
237 Info(
"Krb5Authenticate",
238 "user requested principal: %s", principal.
Data());
240 Info(
"Krb5Authenticate",
241 "default principal: %s", principal.
Data());
244 if ((retval = krb5_cc_get_principal(context, ccdef, &client))) {
246 if (isatty(0) && isatty(1)) {
249 Info(
"Krb5Authenticate",
250 "valid credentials not found: try initializing (Principal: %s)",
253 Error(
"Krb5Authenticate",
"error executing kinit");
256 if ((retval = krb5_cc_get_principal(context, ccdef, &client))) {
257 Error(
"Krb5Authenticate",
"failed <krb5_cc_get_principal>: %s\n",
258 error_message(retval));
263 "not a tty: cannot prompt for credentials, returning failure");
271 TString(
Form(
"%.*s@%.*s",client->data->length, client->data->data,
272 client->realm.length, client->realm.data));
277 if (isatty(0) && isatty(1) && principal != ticketPrincipal) {
279 Info(
"Krb5Authenticate",
280 "got credentials for different principal %s - try"
281 " initialization credentials for principal: %s",
282 ticketPrincipal.
Data(), principal.
Data());
284 Error(
"Krb5Authenticate",
"error executing kinit");
287 if ((retval = krb5_cc_get_principal(context, ccdef, &client))) {
288 Error(
"Krb5Authenticate",
"failed <krb5_cc_get_principal>: %s\n",
289 error_message(retval));
294 TString(
Form(
"%.*s@%.*s",client->data->length, client->data->data,
295 client->realm.length, client->realm.data));
299 cleanup.fClient = client;
302 if (
Krb5CheckCred(context, ccdef, ticketPrincipal, expDate) != 1) {
307 if (isatty(0) && isatty(1)) {
310 Info(
"Krb5Authenticate",
311 "credentials found have expired: try initializing"
312 " (Principal: %s)", ticketPrincipal.
Data());
314 Error(
"Krb5Authenticate",
"error executing kinit");
317 if ((retval = krb5_cc_get_principal(context, ccdef, &client))) {
318 Error(
"Krb5Authenticate",
"failed <krb5_cc_get_principal>: %s\n",
319 error_message(retval));
323 if (
Krb5CheckCred(context, ccdef, ticketPrincipal, expDate) != 1) {
324 Info(
"Krb5Authenticate",
325 "ticket re-initialization failed for principal %s",
326 ticketPrincipal.
Data());
331 "not a tty: cannot prompt for credentials, returning failure");
335 cleanup.fClient = client;
339 Info(
"Krb5Authenticate",
340 "using valid ticket for principal: %s", ticketPrincipal.
Data());
343 TString normUser(client->data->data, client->data->length);
346 Info(
"Krb5Authenticate",
"cc_get_principal: client: %.*s %.*s",
347 client->data->length, client->data->data,
348 client->realm.length, client->realm.data);
351 Int_t reuse = 1, prompt = 0;
361 details =
Form(
"pt:%d ru:%d us:%s", prompt, reuse, ticketPrincipal.
Data());
366 TString options(
Form(
"%d %d %s", opt, normUser.Length(), normUser.Data()));
391 Error(
"Krb5Authenticate",
392 "%s@%s does not accept connections from %s%s",
398 Error(
"Krb5Authenticate",
399 "%s@%s does not accept %s authentication from %s@%s",
412 Error(
"Krb5Authenticate",
"Sending kROOTD_KRB5");
415 nrec = sock->
Recv(retval, kind);
417 Error(
"Krb5Authenticate",
"Receiving kROOTD_KRB5");
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));
444 krb5_principal server;
447 Info(
"Krb5Authenticate",
"serv_host: %s service: %s",
448 serv_host.Data(),service.
Data());
450 if ((retval = krb5_sname_to_principal(context, serv_host.Data(),
451 service.
Data(), KRB5_NT_SRV_HST, &server))) {
453 Error(
"Krb5Authenticate",
"failed <krb5_sname_to_principal>: %s\n",
454 error_message(retval));
457 cleanup.fServer = server;
460 Info(
"Krb5Authenticate",
"sname_to_principal: server: %.*s %.*s",
461 server->data->length, server->data->data,
462 server->realm.length, server->realm.data);
466 krb5_auth_context auth_context = 0;
468 char proto_version[100] =
"krootd_v_1";
469 krb5_data cksum_data;
470 cksum_data.data = (
char *)serv_host.Data();
471 cksum_data.length = serv_host.Length();
473 krb5_ap_rep_enc_part *rep_ret;
475 retval = krb5_auth_con_init(context, &auth_context);
477 Error(
"Krb5Authenticate",
"failed auth_con_init: %s\n",
478 error_message(retval));
479 cleanup.fAuthContext = auth_context;
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));
487 Info(
"Krb5Authenticate",
488 "Sending kerberos authentication to %s",
491 retval = krb5_sendauth(context, &auth_context, (krb5_pointer)&sockd,
492 proto_version, client, server,
493 AP_OPTS_MUTUAL_REQUIRED,
496 ccdef, &err_ret, &rep_ret, 0);
500 if (retval && retval != KRB5_SENDAUTH_REJECTED) {
501 Error(
"Krb5Authenticate",
"failed <krb5_sendauth>: %s\n",
502 error_message(retval));
505 if (retval == KRB5_SENDAUTH_REJECTED) {
507 Error(
"Krb5Authenticate",
"sendauth rejected, error reply "
509 err_ret->text.length, err_ret->text.data);
511 }
else if (!rep_ret) {
515 cleanup.fRepRet = rep_ret;
522 Info(
"Krb5Authenticate",
"client is %s target is %s",
523 normUser.Data(),targetUser.
Data());
526 Error(
"Krb5Authenticate",
"Sending <targetUser>");
536 retval = krb5_auth_con_genaddrs(context, auth_context,
537 sockd, KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR);
540 Error(
"Krb5Authenticate",
"failed auth_con_genaddrs is: %s\n",
541 error_message(retval));
544 retval = krb5_fwd_tgt_creds(context, auth_context, 0 ,
545 client, server, ccdef,
true,
548 Error(
"Krb5Authenticate",
"fwd_tgt_creds failed: %s\n",
549 error_message(retval));
553 cleanup.fData = outdata.data;
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]);
563 snprintf(buflen, 20,
"%d", outdata.length);
566 Error(
"Krb5Authenticate",
"Sending <buflen>");
571 nsen = sock->
SendRaw(outdata.data, outdata.length);
573 Error(
"Krb5Authenticate",
"Sending <Key>");
578 Info(
"Krb5Authenticate",
579 "For kerberos forward ticket sent %d bytes (expected %d)",
580 nsen, outdata.length);
589 nrec = sock->
Recv(answer, 100, type);
597 Error(
"Krb5Authenticate",
"Receiving <user@realm>");
601 Info(
"Krb5Auth",
"%s",answer);
606 nrec = sock->
Recv(retval, type);
608 Error(
"Krb5Authenticate",
"Receiving <key request>");
617 "problems recvn RSA key flag: got message %d, flag: %d",
627 nrec = sock->
Recv(retval, type);
629 Error(
"Krb5Authenticate",
"Receiving <length of user+offset string>");
636 "problems recvn (user,offset) length (%d:%d bytes:%d)",
640 char *rfrm =
new char[retval+1];
641 nrec = sock->
Recv(rfrm,retval+1, type);
643 Error(
"Krb5Authenticate",
"Receiving <user+offset string>");
651 sscanf(rfrm,
"%127s %d", lUser, &offset);
657 if (reuse == 1 && offset > -1) {
660 "problems secure-receiving token - may result in corrupted token");
663 Info(
"Krb5Auth",
"received from server: token: '%s' ", token);
672 details, token, expDate, 0, rsaKey);
677 if (token)
delete[] token;
679 nrec = sock->
Recv(answer, 100, type);
681 Error(
"Krb5Authenticate",
"Receiving <user string>");
698 nrec = sock->
Recv(authok, kind);
700 Error(
"Krb5Authenticate",
"Receiving <Auth flag>");
716 Info(
"Krb5InitCred",
"enter: %s", clientPrincipal);
721 const char *usr = Getline(
Form(
"Principal (%s): ", principal.
Data()));
733 if (strlen(R__KRB5INIT) <= 0)
734 cmd =
Form(
"/usr/kerberos/bin/kinit -f %s", principal.
Data());
736 cmd =
Form(
"%s -f %s",R__KRB5INIT, principal.
Data());
739 Info(
"Krb5InitCred",
"executing: %s", cmd.
Data());
743 Info(
"Krb5InitCred",
"error: return code: %d", rc);
762 Info(
"Krb5CheckCred",
"enter: principal '%s'", principal.
Data());
768 if ((retval = krb5_cc_start_seq_get(kCont, Cc, &cur))) {
770 Error(
"Krb5Authenticate",
"failed <krb5_cc_start_seq_get>: %s\n",
771 error_message(retval));
776 while (!(retval = krb5_cc_next_cred(kCont, Cc, &cur, &creds)) && valid == -1) {
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,
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,
789 Info(
"Krb5CheckCred",
"Endtime: %d ", creds.times.endtime);
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)) {
800 valid = (creds.times.endtime >= now) ? 1 : 0;
802 expDate.Set(creds.times.endtime);
804 krb5_free_cred_contents(kCont, &creds);
820 if (strstr(ctx->
GetID(), principal))
Int_t Krb5Authenticate(TAuthenticate *, TString &, TString &, Int_t)
Kerberos v5 authentication code.
static void SetKrb5AuthHook(Krb5Auth_t func)
Set kerberos5 authorization function.
static Bool_t GetAuthReUse()
Static method returning the authentication reuse settings.
const char * GetHostName() 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...
const char * GetUser() const
Int_t GetServType() const
static TKrb5AuthInit gKrb5authInit
virtual Int_t Send(const TMessage &mess)
Send a TMessage object.
virtual Int_t Recv(TMessage *&mess)
Receive a TMessage object.
const char * GetRemoteHost() const
TSocket * GetSocket() const
Bool_t IsActive() const
Check remote OffSet and expiring Date.
static Int_t Krb5CheckSecCtx(const char *, TRootSecContext *)
Krb5 version of CheckSecCtx to be passed to TAuthenticate::AuthExists Check if principal is matches t...
static const char * GetKrb5Principal()
Static method returning the principal to be used to init Krb5 tickets.
const Int_t kAUTH_RSATY_MSK
static Int_t Krb5InitCred(const char *clientPrincipal, Bool_t promptPrinc=kFALSE)
Checks if there are valid credentials in the cache.
virtual Int_t GetDescriptor() const
const char * Data() const
virtual Int_t SendRaw(const void *buffer, Int_t length, ESendRecvOptions opt=kDefault)
Send a raw buffer of specified length.
const char * GetProtocol() const
virtual const char * Getenv(const char *env)
Get environment variable.
void Info(const char *location, const char *msgfmt,...)
TString & Append(const char *cs)
virtual UserGroup_t * GetUserInfo(Int_t uid)
Returns all user info in the UserGroup_t structure.
static Bool_t GetPromptUser()
Static method returning the prompt user settings.
void Error(const char *location, const char *msgfmt,...)
const Int_t kAUTH_REUSE_MSK
void SetSecContext(TRootSecContext *ctx)
static void AuthError(const char *where, Int_t error)
Print error string depending on error code.
R__EXTERN TSystem * gSystem
Int_t GetRSAKeyType() const
char * Form(const char *fmt,...)
virtual Int_t Exec(const char *shellcmd)
Execute a command.
THostAuth * GetHostAuth() const
void Warning(const char *location, const char *msgfmt,...)
static const char * GetDefaultUser()
Static method returning the default user information.
static Int_t Krb5CheckCred(krb5_context, krb5_ccache, TString, TDatime &)
Checks if there are valid credentials.
char * StrDup(const char *str)
Duplicate the string str.
TString & Remove(Ssiz_t pos)
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...
virtual const char * HostName()
Return the system's host name.
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...
const char * GetID() const
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
TInetAddress GetInetAddress() const
void Resize(Ssiz_t n)
Resize the string. Truncate or add blanks as necessary.
static Int_t SendRSAPublicKey(TSocket *Socket, Int_t key=0)
Receives server RSA Public key Sends local RSA public key encoded.
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
static const char * GetAuthMethod(Int_t idx)
Static method returning the method corresponding to idx.
virtual void IgnoreSignal(ESignals sig, Bool_t ignore=kTRUE)
If ignore is true ignore the specified signal, else restore previous behaviour.