"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "msktname.cpp" between
msktutil-1.1.tar.bz2 and msktutil-1.2.1.tar.gz

About: msktutil is a program for interoperability with Active Directory.

msktname.cpp  (msktutil-1.1.tar.bz2):msktname.cpp  (msktutil-1.2.1)
skipping to change at line 36 skipping to change at line 36
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* *
*----------------------------------------------------------------------------- *-----------------------------------------------------------------------------
*/ */
#include "msktutil.h" #include "msktutil.h"
#include <algorithm> #include <algorithm>
#include <cctype> #include <cctype>
#include <sstream>
std::string complete_hostname(const std::string &hostname, std::string complete_hostname(const std::string &hostname,
bool no_canonical_name) bool no_canonical_name)
{ {
/* Ask the kerberos lib to canonicalize the hostname, and then /* Ask the kerberos lib to canonicalize the hostname, and then
* pull it out of the principal. */ * pull it out of the principal. */
int32_t type = KRB5_NT_SRV_HST; int32_t type = KRB5_NT_SRV_HST;
krb5_principal temp_princ_raw = NULL; krb5_principal temp_princ_raw = NULL;
/* do not canonicalize, use supplied hostname */ /* do not canonicalize, use supplied hostname */
skipping to change at line 57 skipping to change at line 58
type = KRB5_NT_UNKNOWN; type = KRB5_NT_UNKNOWN;
} }
krb5_error_code ret = krb5_sname_to_principal(g_context, krb5_error_code ret = krb5_sname_to_principal(g_context,
hostname.c_str(), hostname.c_str(),
"host", "host",
type, type,
&temp_princ_raw); &temp_princ_raw);
if (ret != 0) { if (ret != 0) {
fprintf(stderr, fprintf(stderr,
"Warning: hostname canonicalization for %s failed (%s)\n", "Warning: hostname canonicalization for %s failed: %s\n",
hostname.c_str(), hostname.c_str(),
error_message(ret) error_message(ret)
); );
return hostname; return hostname;
} }
KRB5Principal temp_princ(temp_princ_raw); KRB5Principal temp_princ(temp_princ_raw);
#ifdef HEIMDAL #ifdef HEIMDAL
const char *comp = krb5_principal_get_comp_string(g_context, const char *comp = krb5_principal_get_comp_string(g_context,
skipping to change at line 135 skipping to change at line 136
"hostname, strange value from " "hostname, strange value from "
"krb5_sname_to_principal."); "krb5_sname_to_principal.");
} }
#ifdef HEIMDAL #ifdef HEIMDAL
return std::string(comp); return std::string(comp);
#else #else
return std::string(comp->data, comp->length); return std::string(comp->data, comp->length);
#endif #endif
} }
bool DnsSrvHost::validate(bool nocanon) { bool DnsSrvHost::validate(bool nocanon, std::string service) {
int sock = -1; int ret, sock = -1;
struct hostent *host; /* used to call into C function, so we prefer char[] over std::string */
char host[NI_MAXHOST];
struct addrinfo *hostaddrinfo = NULL;
// The order of the struct addrinfo members is not portable,
// therefore it is not possible to use struct initialization here.
// Use default initialization and set potentially nonzero members explicitly
.
// See issue #161
struct addrinfo hints = {};
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if (!validated_name.empty()) { if (!validated_name.empty()) {
return true; return true;
} }
host = gethostbyname(srvname.c_str()); /* so far we don't require C++11, so no ::to_string(), yet */
if (service.empty()) {
std::stringstream srvtmp;
srvtmp << m_port;
std::string service = srvtmp.str();
}
ret = getaddrinfo(srvname.c_str(), service.c_str(), &hints, &hostaddrinfo);
if (!host) { if (ret != 0) {
VERBOSE("Error: gethostbyname failed for %s\n", srvname.c_str()); VERBOSE("Error: gethostbyname failed for %s: %s\n", srvname.c_str(),
ret == EAI_SYSTEM ? strerror(errno) : gai_strerror(ret));
if (hostaddrinfo) {
freeaddrinfo(hostaddrinfo);
}
return false; return false;
} }
VERBOSE("Found DC: %s. Checking availability...", srvname.c_str()); VERBOSE("Found DC: %s. Checking availability...", srvname.c_str());
for (int i = 0; host->h_addr_list[i]; i++) { for (struct addrinfo *ai = hostaddrinfo; ai; ai = ai->ai_next) {
struct sockaddr_in addr;
struct hostent *hp;
memcpy(&(addr.sin_addr.s_addr), host->h_addr_list[i], host->h_length);
/* Now let's try and open and close a socket to see if the domain contro ller is up or not */ /* Now let's try and open and close a socket to see if the domain contro ller is up or not */
addr.sin_family = AF_INET;
addr.sin_port = htons(LDAP_PORT);
if (sock != -1) { if (sock != -1) {
close(sock); close(sock);
} }
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { if ((sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) ==
VERBOSE("Failed to open socket"); -1) {
VERBOSE("Failed to open socket: %s", strerror(errno));
continue; continue;
} }
if (connect(sock, (struct sockaddr *) &addr, sizeof(addr)) == -1) { if (connect(sock, (struct sockaddr *) ai->ai_addr, ai->ai_addrlen) == -1
VERBOSE("LDAP connection (%d) failed", i); ) {
int err = errno;
char addrstr[INET6_ADDRSTRLEN] = "";
(void) inet_ntop(ai->ai_family, ai->ai_addr, addrstr, INET6_ADDRSTRL
EN);
VERBOSE("LDAP connection to %s failed: %s", addrstr, strerror(err));
continue; continue;
} }
/* See if this is the 'lowest' domain controller name... the idea is to always try to /* See if this is the 'lowest' domain controller name... the idea is to always try to
* use the same domain controller. Things may become inconsistent otherw ise. * use the same domain controller. Things may become inconsistent otherw ise.
* This optimization is only possible if we're told to canonify the host name. Otherwise, * This optimization is only possible if we're told to canonify the host name. Otherwise,
* we're not allowed to touch it, but we can make sure that it resolves to at least * we're not allowed to touch it, but we can make sure that it resolves to at least
* one working IP address. */ * one working IP address. */
if (nocanon) { if (nocanon) {
validated_name = srvname; validated_name = srvname;
break; break;
} }
hp = gethostbyaddr((char *) &addr.sin_addr.s_addr, sizeof(addr.sin_addr.
s_addr), AF_INET); ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, host, sizeof(host), NULL,
if (!hp) { 0, NI_NAMEREQD);
VERBOSE("Error: gethostbyaddr failed for %s\n", srvname.c_str());
if (ret != 0) {
int err = errno;
char addrstr[INET6_ADDRSTRLEN] = "";
(void) inet_ntop(ai->ai_family, ai->ai_addr, addrstr, INET6_ADDRSTRL
EN);
VERBOSE("Error: getnameinfo failed for %s: %s\n", addrstr,
ret == EAI_SYSTEM ? strerror(err) : gai_strerror(ret));
continue; continue;
} }
if (!validated_name.empty() && std::string(hp->h_name) > validated_name)
{ if (!validated_name.empty() && std::string(host) > validated_name) {
VERBOSE("Connection to DC %s ok, but we already prefer %s", hp->h_na VERBOSE("Connection to DC %s ok, but we already prefer %s", host, va
me, validated_name.c_str()); lidated_name.c_str());
continue; continue;
} }
validated_name = std::string(hp->h_name); validated_name = std::string(host);
} }
if (sock != -1) { if (sock != -1) {
close(sock); close(sock);
} }
if (hostaddrinfo) {
freeaddrinfo(hostaddrinfo);
}
return ! validated_name.empty(); return ! validated_name.empty();
}; };
DnsSrvQuery::DnsSrvQuery(const std::string& domain, const std::string& service, const std::string& protocol) DnsSrvQuery::DnsSrvQuery(const std::string& domain, const std::string& service, const std::string& protocol)
{ {
#if defined(HAVE_LIBUDNS) #if defined(HAVE_LIBUDNS)
struct dns_ctx *nsctx = NULL; struct dns_ctx *nsctx = NULL;
dns_reset(NULL); dns_reset(NULL);
if ((nsctx = dns_new(NULL)) != NULL) { if ((nsctx = dns_new(NULL)) != NULL) {
skipping to change at line 262 skipping to change at line 289
const bool no_reverse_lookups) const bool no_reverse_lookups)
{ {
std::string dc; std::string dc;
int i; int i;
DnsSrvQuery dcsrvs; DnsSrvQuery dcsrvs;
std::string bestdc; std::string bestdc;
std::string protocols[] = { "tcp", "udp" }; std::string protocols[] = { "tcp", "udp" };
if (!site_name.empty()) { if (!site_name.empty()) {
for (i = 0; i < (int)(sizeof(protocols) / sizeof(protocols[0])); i++) { for (i = 0; i < (int)(sizeof(protocols) / sizeof(protocols[0])); i++) {
VERBOSE("Attempting to find site-specific Domain Controller to use v ia " VERBOSE("Attempting to find site-specific domain controller to use v ia "
"DNS SRV record in domain %s for site %s and procoto l %s", "DNS SRV record in domain %s for site %s and procoto l %s",
realm_name.c_str(), site_name.c_str(), protocols[i]. c_str()); realm_name.c_str(), site_name.c_str(), protocols[i]. c_str());
dcsrvs = DnsSrvQuery(site_name + "._sites.dc._msdcs." + realm_name, "kerberos", protocols[i]); dcsrvs = DnsSrvQuery(site_name + "._sites.dc._msdcs." + realm_name, "kerberos", protocols[i]);
if (!dcsrvs.empty()) { if (!dcsrvs.empty()) {
break; break;
} }
} }
} }
if (dcsrvs.empty()) { if (dcsrvs.empty()) {
for (i = 0; i < (int)(sizeof(protocols) / sizeof(protocols[0])); i++) { for (i = 0; i < (int)(sizeof(protocols) / sizeof(protocols[0])); i++) {
VERBOSE("Attempting to find Domain Controller to use via " VERBOSE("Attempting to find domain controller to use via "
"DNS SRV record in domain %s for procotol %s", "DNS SRV record in domain %s for procotol %s",
realm_name.c_str(), protocols[i].c_str()); realm_name.c_str(), protocols[i].c_str());
dcsrvs = DnsSrvQuery("dc._msdcs." + realm_name, "kerberos", protocol s[i]); dcsrvs = DnsSrvQuery("dc._msdcs." + realm_name, "kerberos", protocol s[i]);
if (!dcsrvs.empty()) { if (!dcsrvs.empty()) {
break; break;
} }
} }
} }
if (dcsrvs.empty()) { if (dcsrvs.empty()) {
VERBOSE("Attempting to find a Domain Controller to use (DNS domain)"); VERBOSE("Attempting to find a domain controller to use (DNS domain)");
dcsrvs = DnsSrvQuery(DnsSrvHost(realm_name, 0, 0, 0)); dcsrvs = DnsSrvQuery(DnsSrvHost(realm_name, 0, 0, 0));
} }
for (std::vector<DnsSrvHost>::iterator it=dcsrvs.begin(); it != dcsrvs.end() ; it++) { for (std::vector<DnsSrvHost>::iterator it=dcsrvs.begin(); it != dcsrvs.end() ; it++) {
if (it->validate(no_reverse_lookups)) { /* Don't validate host availability by checking the KRB5 port returned
* from the SRV record, but the hard-coded, standard LDAP port (389).
* This is a short cut that should work as long as each DC runs both
* KRB5 and LDAP on default ports.
*/
if (it->validate(no_reverse_lookups, stringify(LDAP_PORT))) {
bestdc = it->name(); bestdc = it->name();
break; break;
} }
} }
VERBOSE("Found preferred Domain Controller: %s", bestdc.c_str()); VERBOSE("Found preferred domain controller: %s", bestdc.c_str());
return bestdc; return bestdc;
} }
std::string get_host_os()
{
struct utsname info;
int ret;
ret = uname(&info);
if (ret == -1) {
fprintf(stderr, "Error: uname failed (%d)\n", ret);
return NULL;
}
return std::string(info.sysname);
}
/* Return true if <str> ends with <suffix>, false otherwise */ /* Return true if <str> ends with <suffix>, false otherwise */
static bool ends_with(std::string const &str, std::string const &suffix) static bool ends_with(std::string const &str, std::string const &suffix)
{ {
if (suffix.size() > str.size()) if (suffix.size() > str.size())
return false; return false;
return std::equal(suffix.rbegin(), suffix.rend(), str.rbegin()); return std::equal(suffix.rbegin(), suffix.rend(), str.rbegin());
} }
/* Default sAMAccountName for current host: /* Default sAMAccountName for current host:
 End of changes. 19 change blocks. 
46 lines changed or deleted 69 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)