XRootD
XrdNetIdentity.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d N e t I d e n t i t y . h h */
4 /* */
5 /* (c) 2021 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* Produced by Andrew Hanushevsky for Stanford University under contract */
7 /* DE-AC02-76-SFO0515 with the Department of Energy */
8 /* */
9 /* This file is part of the XRootD software suite. */
10 /* */
11 /* XRootD is free software: you can redistribute it and/or modify it under */
12 /* the terms of the GNU Lesser General Public License as published by the */
13 /* Free Software Foundation, either version 3 of the License, or (at your */
14 /* option) any later version. */
15 /* */
16 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19 /* License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24 /* */
25 /* The copyright holder's institutional names and contributor's names may not */
26 /* be used to endorse or promote products derived from this software without */
27 /* specific prior written permission of the institution or contributor. */
28 /******************************************************************************/
29 
30 #include <string.h>
31 #include <unistd.h>
32 
33 #include "XrdNet/XrdNetAddr.hh"
34 #include "XrdNet/XrdNetIdentity.hh"
35 #include "XrdNet/XrdNetIF.hh"
36 #include "XrdOuc/XrdOucTList.hh"
37 #include "XrdOuc/XrdOucUtils.hh"
38 #include "XrdSys/XrdSysE2T.hh"
39 
40 /******************************************************************************/
41 /* O n e T i m e S t a t i c I n i t i a l i z a t i o n */
42 /******************************************************************************/
43 
44 // Note that we are gauranteed that this will be fully initialzed prior
45 // to any method called that uses these values irrespective of static
46 // initialization order, even though statically initialized.
47 
48 static char DNS_FQN[256]; // Fully qualified hostname
49 static const char *DNS_Domain; // Starts with leading dot, points into DNS_FQN!
50 static const char *DNS_Error; // Error indicator for debugging only
51 
52 static bool getMyFQN()
53 {
54 // Initialize name, domain, and error to empty strings
55 //
56  memset(DNS_FQN, '\0', sizeof(DNS_FQN));
58  DNS_Error = nullptr;
59 
60 // The identity can be specified via an envar. In this case, it short circuits
61 // all the subsequent code.
62 //
63  const char *dnsName = nullptr;
64  if ((dnsName = getenv("XRDNET_IDENTITY")))
65  {strlcpy(DNS_FQN, dnsName, sizeof(DNS_FQN));
67  if (XrdNetAddrInfo::isHostName(DNS_FQN) && !(DNS_Domain = index(DNS_FQN, '.')))
68  DNS_Domain = "";
69  return false;
70  }
71 
72 // Obtain the host name, this is mandatory.
73 //
74  if (gethostname(DNS_FQN, sizeof(DNS_FQN)))
75  {DNS_Error = XrdSysE2T(errno); DNS_Domain = ""; return false;}
76 
77  int hnLen = strlen(DNS_FQN);
79 
80 // First step it to get all IP addresses configured on this machine
81 //
82  XrdOucTList *ifList = nullptr;
83  if (!XrdNetIF::GetIF(&ifList, &DNS_Error))
84  {DNS_Domain = ""; return true;}
85 
86 // Run through the interfaces and try to get the hostname associated with
87 // this machine. Note that we may have public and private addresses and
88 // they may have different hostname attached. We only accept the hostname
89 // that matches what is returned by gethostname().
90 //
91  XrdNetAddr theAddr;
92  const char *domP = nullptr;
93  char *theIPA[2] = { nullptr, nullptr };
94  char *theName[2] = { nullptr, nullptr };
95  XrdOucTList *ifNow = nullptr;
96 
97  while((ifNow = ifList))
98  {int i = (ifNow->sval[1] ? 1 : 0); // Private | public
99 
100  if (i >= 0 && theName[i] == 0 && !theAddr.Set(ifNow->text, 0)
101  && (dnsName = theAddr.Name(0,&DNS_Error)) && (domP = index(dnsName,'.')))
102  {int n = domP - dnsName;
103  if (n == hnLen && !strncmp(DNS_FQN, dnsName, n))
104  {theName[i] = strdup(dnsName);
105  } else {
106  if (theIPA[i]) free(theIPA[i]);
107  theIPA[i] = strdup(ifNow->text);
108  }
109  }
110  ifList = ifList->next;
111  delete ifNow;
112  }
113 
114 // Fix up error pointer
115 //
116  if (DNS_Error == 0) DNS_Error = "no error";
117 
118 // We prefer the public name should we have it
119 //
120  if (theName[0])
121  {strlcpy(DNS_FQN, theName[0], sizeof(DNS_FQN));
122  goto done;
123  }
124 
125 // Use the private name should we have it
126 //
127  if (theName[1])
128  {strlcpy(DNS_FQN, theName[1], sizeof(DNS_FQN));
129  goto done;
130  }
131 
132 // Concote a name using old-style DNS resolution. This may not work if DNS
133 // namespaces are being used (e.g. k8s environments) or if the hostname is not
134 // resolvable. We will catch that here and move on.
135 //
136  if ((DNS_Error = theAddr.Set(DNS_FQN,0))) dnsName = nullptr;
137  else dnsName = theAddr.Name(0, &DNS_Error);
138 
139 // Check if this worked
140 //
141  if (dnsName)
142  {strlcpy(DNS_FQN, dnsName, sizeof(DNS_FQN));
143  goto done;
144  }
145 
146 // Prefrentially return the hostname as an address as the value of gethostname()
147 // may actually fail. So, we defer naming the machine until later but we do
148 // know its IP address and that can be used as an identity. Return the public
149 // address first. Note that we prefrentially return the IPv6 address here.
150 //
151  if (theIPA[0])
152  {strlcpy(DNS_FQN, theIPA[0], sizeof(DNS_FQN));
153  goto done;
154  }
155 
156  if (theIPA[1])
157  {strlcpy(DNS_FQN, theIPA[1], sizeof(DNS_FQN));
158  goto done;
159  }
160 
161 // Fallback to using the simple unqualified hostname, this still may be OK but
162 // this is likely to fail in certain situations where DNS is screwed up.
163 //
164  DNS_Domain = "";
165  return true;
166 
167 done:
168  free(theName[0]);
169  free(theName[1]);
170  free(theIPA[0]);
171  free(theIPA[1]);
172 
173  if (!(DNS_Domain = index(DNS_FQN, '.')))
174  DNS_Domain = "";
175  return true;
176 }
177 
178 // True if the FQN is configured for this host
179 static bool FQN_DNS = getMyFQN();
180 
181 /******************************************************************************/
182 /* D o m a i n */
183 /******************************************************************************/
184 
185 const char *XrdNetIdentity::Domain(const char **eText)
186 {
187  if (eText) *eText = DNS_Error;
188  return DNS_Domain;
189 }
190 
191 /******************************************************************************/
192 /* F Q N */
193 /******************************************************************************/
194 
195 const char *XrdNetIdentity::FQN(const char **eText)
196 {
197  if (eText) *eText = DNS_Error;
198  return DNS_FQN;
199 }
200 
201 /******************************************************************************/
202 /* s e t F Q N */
203 /******************************************************************************/
204 
205 void XrdNetIdentity::SetFQN(const char *fqn)
206 {
207  strlcpy(DNS_FQN, fqn, sizeof(DNS_FQN));
208  if (!(DNS_Domain = index(DNS_FQN, '.'))) DNS_Domain = "";
209  FQN_DNS = false;
210 }
static bool FQN_DNS
static const char * DNS_Error
static bool getMyFQN()
static const char * DNS_Domain
static char DNS_FQN[256]
const char * XrdSysE2T(int errcode)
Definition: XrdSysE2T.cc:104
size_t strlcpy(char *dst, const char *src, size_t sz)
static bool isHostName(const char *name)
const char * Name(const char *eName=0, const char **eText=0)
const char * Set(const char *hSpec, int pNum=PortInSpec)
Definition: XrdNetAddr.cc:216
static int GetIF(XrdOucTList **ifList, const char **eText=0)
Definition: XrdNetIF.cc:413
static void SetFQN(const char *fqn)
static const char * Domain(const char **eText=0)
static const char * FQN(const char **etext=0)
XrdOucTList * next
Definition: XrdOucTList.hh:45
char * text
Definition: XrdOucTList.hh:46
static void toLower(char *str)