summaryrefslogtreecommitdiffstats
path: root/src/windows/identity/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/windows/identity/plugins')
-rw-r--r--src/windows/identity/plugins/krb4/krb4configdlg.c2
-rw-r--r--src/windows/identity/plugins/krb4/krbcred.h2
-rw-r--r--src/windows/identity/plugins/krb5/errorfuncs.c46
-rw-r--r--src/windows/identity/plugins/krb5/krb5funcs.c2
-rw-r--r--src/windows/identity/plugins/krb5/krb5identpro.c43
-rw-r--r--src/windows/identity/plugins/krb5/krb5main.c2
-rw-r--r--src/windows/identity/plugins/krb5/krb5newcreds.c215
-rw-r--r--src/windows/identity/plugins/krb5/krbconfig.csv2
-rw-r--r--src/windows/identity/plugins/krb5/lang/en_us/langres.rc2
-rw-r--r--src/windows/identity/plugins/krb5/lang/krb5_msgs.mc36
10 files changed, 321 insertions, 31 deletions
diff --git a/src/windows/identity/plugins/krb4/krb4configdlg.c b/src/windows/identity/plugins/krb4/krb4configdlg.c
index 3186633c4..6c2b02d43 100644
--- a/src/windows/identity/plugins/krb4/krb4configdlg.c
+++ b/src/windows/identity/plugins/krb4/krb4configdlg.c
@@ -280,7 +280,7 @@ krb4_id_config_proc(HWND hwnd,
khc_close_space(csp_ident);
if (csp_idk4)
- khc_close_space(csp_ident);
+ khc_close_space(csp_idk4);
khui_cfg_set_flags_inst(d,
((applied)? KHUI_CNFLAG_APPLIED: 0),
diff --git a/src/windows/identity/plugins/krb4/krbcred.h b/src/windows/identity/plugins/krb4/krbcred.h
index f31c4a4d3..7c3b31a13 100644
--- a/src/windows/identity/plugins/krb4/krbcred.h
+++ b/src/windows/identity/plugins/krb4/krbcred.h
@@ -29,7 +29,7 @@
#include<windows.h>
-#define KHERR_FACILITY L"Kerberos4"
+#define KHERR_FACILITY L"Krb4Cred"
#define KHERR_FACILITY_ID 65
#define KHERR_HMODULE hResModule
diff --git a/src/windows/identity/plugins/krb5/errorfuncs.c b/src/windows/identity/plugins/krb5/errorfuncs.c
index d2fabbad4..f631b3c0c 100644
--- a/src/windows/identity/plugins/krb5/errorfuncs.c
+++ b/src/windows/identity/plugins/krb5/errorfuncs.c
@@ -77,12 +77,20 @@ void khm_err_describe(long code, wchar_t * buf, khm_size cbbuf,
*suggestion = 0;
*suggest_code = KHERR_SUGGEST_NONE;
+ if (WSABASEERR <= code && code < (WSABASEERR + 1064)) {
+ /* winsock error */
+ table_num = WSABASEERR;
+ offset = code - WSABASEERR;
+ }
+
switch(table_num)
{
case krb_err_base:
case kadm_err_base:
+ case WSABASEERR:
break;
default:
+
if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
*suggestion = MSG_ERR_S_INTEGRITY;
}
@@ -91,9 +99,8 @@ void khm_err_describe(long code, wchar_t * buf, khm_size cbbuf,
return;
}
- if (table_num == krb_err_base)
- switch(offset)
- {
+ if (table_num == krb_err_base) {
+ switch(offset) {
case KDC_NAME_EXP: /* 001 Principal expired */
case KDC_SERVICE_EXP: /* 002 Service expired */
case KDC_AUTH_EXP: /* 003 Auth expired */
@@ -170,9 +177,8 @@ void khm_err_describe(long code, wchar_t * buf, khm_size cbbuf,
/* no extra error msg */
break;
}
- else
- switch(code)
- {
+ } else if (table_num == kadm_err_base) {
+ switch(code) {
case KADM_INSECURE_PW:
/* if( kadm_info != NULL ){
* wsprintf(buf, "%s\n%s", com_err_msg, kadm_info);
@@ -198,6 +204,34 @@ void khm_err_describe(long code, wchar_t * buf, khm_size cbbuf,
/* no extra error msg */
break;
}
+ } else if (table_num == WSABASEERR) {
+ switch(code) {
+ case WSAENETDOWN:
+ msg_id = MSG_ERR_NETDOWN;
+ sugg_id = MSG_ERR_S_NETRETRY;
+ sugg_code = KHERR_SUGGEST_RETRY;
+ break;
+
+ case WSATRY_AGAIN:
+ msg_id = MSG_ERR_TEMPDOWN;
+ sugg_id = MSG_ERR_S_TEMPDOWN;
+ sugg_code = KHERR_SUGGEST_RETRY;
+ break;
+
+ case WSAENETUNREACH:
+ case WSAENETRESET:
+ case WSAECONNABORTED:
+ case WSAECONNRESET:
+ case WSAETIMEDOUT:
+ case WSAECONNREFUSED:
+ case WSAEHOSTDOWN:
+ case WSAEHOSTUNREACH:
+ msg_id = MSG_ERR_NOHOST;
+ sugg_id = MSG_ERR_S_NOHOST;
+ sugg_code = KHERR_SUGGEST_RETRY;
+ break;
+ }
+ }
if (msg_id != 0) {
FormatMessage(FORMAT_MESSAGE_FROM_HMODULE |
diff --git a/src/windows/identity/plugins/krb5/krb5funcs.c b/src/windows/identity/plugins/krb5/krb5funcs.c
index 316263119..7db09526d 100644
--- a/src/windows/identity/plugins/krb5/krb5funcs.c
+++ b/src/windows/identity/plugins/krb5/krb5funcs.c
@@ -2056,7 +2056,7 @@ khm_krb5_changepwd(char * principal,
char** error_str)
{
krb5_error_code rc = 0;
- int result_code;
+ int result_code = 0;
krb5_data result_code_string, result_string;
krb5_context context = 0;
krb5_principal princ = 0;
diff --git a/src/windows/identity/plugins/krb5/krb5identpro.c b/src/windows/identity/plugins/krb5/krb5identpro.c
index b263e6bf3..11a7410b1 100644
--- a/src/windows/identity/plugins/krb5/krb5identpro.c
+++ b/src/windows/identity/plugins/krb5/krb5identpro.c
@@ -49,15 +49,52 @@ typedef struct tag_k5_new_cred_data {
HWND hw_realm;
} k5_new_cred_data;
+static
+void
+trim_str(wchar_t * s, khm_size cch) {
+ wchar_t * c, * last_ws;
+
+ for (c = s; *c && iswspace(*c) && ((khm_size)(c - s)) < cch; c++);
+
+ if (((khm_size)(c - s)) >= cch)
+ return;
+
+ if (c != s && ((khm_size)(c - s)) < cch) {
+#if _MSC_VER >= 1400
+ wmemmove_s(s, cch, c, cch - ((khm_size)(c - s)));
+#else
+ memmove(s, c, (cch - ((khm_size)(c - s))) * sizeof(wchar_t));
+#endif
+ }
+
+ last_ws = NULL;
+ for (c = s; *c && ((khm_size)(c - s)) < cch; c++) {
+ if (!iswspace(*c))
+ last_ws = NULL;
+ else if (last_ws == NULL)
+ last_ws = c;
+ }
+
+ if (last_ws)
+ *last_ws = L'\0';
+}
+
/* Runs in the UI thread */
int
k5_get_realm_from_nc(khui_new_creds * nc,
wchar_t * buf,
khm_size cch_buf) {
k5_new_cred_data * d;
+ khm_size s;
d = (k5_new_cred_data *) nc->ident_aux;
- return GetWindowText(d->hw_realm, buf, (int) cch_buf);
+ buf[0] = L'\0';
+ GetWindowText(d->hw_realm, buf, (int) cch_buf);
+ trim_str(buf, cch_buf);
+
+ StringCchLength(buf, cch_buf, &s);
+
+ return (int) s;
}
/* set the primary identity of a new credentials dialog depending on
@@ -83,6 +120,7 @@ set_identity_from_ui(khui_new_creds * nc,
assert(cch < KCDB_IDENT_MAXCCH_NAME - 1);
GetWindowText(d->hw_username, un, ARRAYLENGTH(un));
+ trim_str(un, ARRAYLENGTH(un));
realm = khm_get_realm_from_princ(un);
if (realm) /* realm was specified */
@@ -113,6 +151,7 @@ set_identity_from_ui(khui_new_creds * nc,
}
GetWindowText(d->hw_realm, realm, (int) cch_left);
+ trim_str(realm, cch_left);
_set_ident:
if (KHM_FAILED(rv = kcdb_identity_create(un,
@@ -183,6 +222,7 @@ update_crossfeed(khui_new_creds * nc,
GetWindowText(d->hw_username,
un,
ARRAYLENGTH(un));
+ trim_str(un, ARRAYLENGTH(un));
un_realm = khm_get_realm_from_princ(un);
@@ -246,6 +286,7 @@ update_crossfeed(khui_new_creds * nc,
GetWindowText(d->hw_realm, realm,
ARRAYLENGTH(realm));
+ trim_str(realm, ARRAYLENGTH(realm));
idx = (int)SendMessage(d->hw_realm,
CB_FINDSTRINGEXACT,
diff --git a/src/windows/identity/plugins/krb5/krb5main.c b/src/windows/identity/plugins/krb5/krb5main.c
index 97ef85ee9..f1b7f0549 100644
--- a/src/windows/identity/plugins/krb5/krb5main.c
+++ b/src/windows/identity/plugins/krb5/krb5main.c
@@ -30,7 +30,7 @@
kmm_module h_khModule; /* KMM's handle to this module */
HINSTANCE hInstance;
HMODULE hResModule; /* HMODULE to the resource library */
-const wchar_t * k5_facility = L"Krb5";
+const wchar_t * k5_facility = L"Krb5Cred";
khm_int32 type_id_enctype = -1;
khm_int32 type_id_addr_list = -1;
diff --git a/src/windows/identity/plugins/krb5/krb5newcreds.c b/src/windows/identity/plugins/krb5/krb5newcreds.c
index 179ec4ede..db9462eb6 100644
--- a/src/windows/identity/plugins/krb5/krb5newcreds.c
+++ b/src/windows/identity/plugins/krb5/krb5newcreds.c
@@ -55,6 +55,7 @@ typedef struct k5_dlg_data_t {
wchar_t * cred_message; /* overrides the credential text, if
non-NULL */
+ BOOL pwd_change; /* force a password change */
} k5_dlg_data;
@@ -186,6 +187,56 @@ k5_handle_wmnc_notify(HWND hwnd,
}
break;
+ case WMNC_CREDTEXT_LINK:
+ {
+ k5_dlg_data * d;
+ khui_htwnd_link * l;
+ khui_new_creds * nc;
+ wchar_t linktext[128];
+
+ d = (k5_dlg_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+ nc = d->nc;
+ l = (khui_htwnd_link *) lParam;
+
+ if (!l)
+ break;
+
+ StringCchCopyN(linktext, ARRAYLENGTH(linktext),
+ l->id, l->id_len);
+
+ if (!wcscmp(linktext, L"Krb5Cred:!Passwd")) {
+ /* we are turning this dialog into a change password dialog... */
+ wchar_t wbuf[KHUI_MAXCCH_BANNER];
+
+ khui_cw_clear_prompts(nc);
+
+ LoadString(hResModule, IDS_NC_PWD_BANNER,
+ wbuf, ARRAYLENGTH(wbuf));
+ khui_cw_begin_custom_prompts(nc, 3, NULL, wbuf);
+
+ LoadString(hResModule, IDS_NC_PWD_PWD,
+ wbuf, ARRAYLENGTH(wbuf));
+ khui_cw_add_prompt(nc, KHUI_NCPROMPT_TYPE_PASSWORD,
+ wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN);
+
+ LoadString(hResModule, IDS_NC_PWD_NPWD,
+ wbuf, ARRAYLENGTH(wbuf));
+ khui_cw_add_prompt(nc, KHUI_NCPROMPT_TYPE_NEW_PASSWORD,
+ wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN);
+
+ LoadString(hResModule, IDS_NC_PWD_NPWD_AGAIN,
+ wbuf, ARRAYLENGTH(wbuf));
+ khui_cw_add_prompt(nc, KHUI_NCPROMPT_TYPE_NEW_PASSWORD_AGAIN,
+ wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN);
+
+ d->pwd_change = TRUE;
+
+ return TRUE;
+ }
+ }
+ break;
+
case WMNC_UPDATE_CREDTEXT:
{
k5_dlg_data * d;
@@ -215,7 +266,8 @@ k5_handle_wmnc_notify(HWND hwnd,
KHM_SUCCEEDED(kcdb_identity_get_flags(nc->identities[0],
&flags)) &&
(flags & KCDB_IDENT_FLAG_VALID) &&
- nc->subtype == KMSG_CRED_NEW_CREDS) {
+ nc->subtype == KMSG_CRED_NEW_CREDS &&
+ !d->pwd_change) {
if (is_k5_identpro)
k5_get_realm_from_nc(nc, tbuf, ARRAYLENGTH(tbuf));
@@ -237,7 +289,8 @@ k5_handle_wmnc_notify(HWND hwnd,
StringCbCopy(nct->credtext, cbsize, sbuf);
} else if (nc->n_identities > 0 &&
- nc->subtype == KMSG_CRED_PASSWORD) {
+ (nc->subtype == KMSG_CRED_PASSWORD ||
+ (nc->subtype == KMSG_CRED_NEW_CREDS && d->pwd_change))) {
cbsize = sizeof(tbuf);
kcdb_identity_get_name(nc->identities[0], tbuf, &cbsize);
@@ -630,6 +683,9 @@ k5_cached_kinit_prompter(void) {
khm_size n_cur_prompts;
khm_int32 n_prompts;
khm_int32 i;
+ khm_int64 iexpiry;
+ FILETIME expiry;
+ FILETIME current;
#ifdef DEBUG
assert(g_fjob.nc);
@@ -656,6 +712,30 @@ k5_cached_kinit_prompter(void) {
goto _cleanup;
+ if (KHM_SUCCEEDED(khc_read_int64(csp_prcache, L"ExpiresOn", &iexpiry))) {
+ /* has the cache expired? */
+ expiry = IntToFt(iexpiry);
+ GetSystemTimeAsFileTime(&current);
+
+ if (CompareFileTime(&expiry, &current) < 0)
+ /* already expired */
+ goto _cleanup;
+ } else {
+ FILETIME lifetime;
+ khm_int32 t;
+
+ /* make the cache expire at some point */
+ GetSystemTimeAsFileTime(&current);
+ khc_read_int32(csp_params, L"PromptCacheLifetime", &t);
+ if (t == 0)
+ t = 172800; /* 48 hours */
+ TimetToFileTimeInterval(t, &lifetime);
+ expiry = FtAdd(&current, &lifetime);
+ iexpiry = FtToInt(&expiry);
+
+ khc_write_int64(csp_prcache, L"ExpiresOn", iexpiry);
+ }
+
/* we found a prompt cache. We take this to imply that the
principal is valid. */
g_fjob.valid_principal = TRUE;
@@ -968,6 +1048,11 @@ k5_kinit_prompter(krb5_context context,
{
wchar_t wbanner[KHUI_MAXCCH_BANNER];
wchar_t wname[KHUI_MAXCCH_PNAME];
+ FILETIME current;
+ FILETIME lifetime;
+ FILETIME expiry;
+ khm_int64 iexpiry;
+ khm_int32 t = 0;
if(banner)
AnsiStrToUnicode(wbanner, sizeof(wbanner), banner);
@@ -982,28 +1067,40 @@ k5_kinit_prompter(krb5_context context,
(banner)?wbanner:NULL,
(name)?wname:NULL);
- if (banner && csp_prcache)
- khc_write_string(csp_prcache,
- L"Banner",
- wbanner);
- else if (csp_prcache)
- khc_write_string(csp_prcache,
- L"Banner",
- L"");
+ if (csp_prcache) {
- if (name && csp_prcache)
- khc_write_string(csp_prcache,
- L"Name",
- wname);
- else if (csp_prcache)
- khc_write_string(csp_prcache,
- L"Name",
- L"");
+ if (banner)
+ khc_write_string(csp_prcache,
+ L"Banner",
+ wbanner);
+ else
+ khc_write_string(csp_prcache,
+ L"Banner",
+ L"");
+
+ if (name)
+ khc_write_string(csp_prcache,
+ L"Name",
+ wname);
+ else if (csp_prcache)
+ khc_write_string(csp_prcache,
+ L"Name",
+ L"");
- if (csp_prcache)
khc_write_int32(csp_prcache,
L"PromptCount",
(khm_int32) num_prompts);
+
+ GetSystemTimeAsFileTime(&current);
+ khc_read_int32(csp_params, L"PromptCacheLifetime", &t);
+ if (t == 0)
+ t = 172800; /* 48 hours */
+ TimetToFileTimeInterval(t, &lifetime);
+ expiry = FtAdd(&current, &lifetime);
+ iexpiry = FtToInt(&expiry);
+
+ khc_write_int64(csp_prcache, L"ExpiresOn", iexpiry);
+ }
}
for(i=0; i < num_prompts; i++) {
@@ -1757,6 +1854,10 @@ k5_msg_cred_dialog(khm_int32 msg_type,
}
khui_cw_unlock_nc(nc);
+
+ /* reset the force-password-change flag if this is a new
+ identity. */
+ d->pwd_change = FALSE;
}
/* fallthrough */
@@ -1950,6 +2051,11 @@ k5_msg_cred_dialog(khm_int32 msg_type,
if (nc->subtype == KMSG_CRED_NEW_CREDS) {
d = (k5_dlg_data *) nct->aux;
+ if (d->pwd_change) {
+ /* we are forcing a password change */
+ goto change_password;
+ }
+
_begin_task(0);
_report_mr0(KHERR_NONE, MSG_CTX_INITAL_CREDS);
_describe();
@@ -2259,6 +2365,9 @@ k5_msg_cred_dialog(khm_int32 msg_type,
} else if (nc->subtype == KMSG_CRED_PASSWORD &&
nc->result == KHUI_NC_RESULT_PROCESS) {
+ change_password:
+ /* we jump here if there was a password change forced */
+
_begin_task(0);
_report_mr0(KHERR_NONE, MSG_CTX_PASSWD);
_describe();
@@ -2360,6 +2469,74 @@ k5_msg_cred_dialog(khm_int32 msg_type,
if (code)
rv = KHM_ERROR_UNKNOWN;
+ else if (nc->subtype == KMSG_CRED_NEW_CREDS) {
+ khm_handle csp_idcfg = NULL;
+ krb5_context ctx = NULL;
+
+ /* we forced a password change. now we need
+ to get the initial credentials. */
+
+ d = (k5_dlg_data *) nct->aux;
+
+ if (d == NULL) {
+ rv = KHM_ERROR_UNKNOWN;
+ goto _pwd_exit;
+ }
+
+ code = khm_krb5_kinit(NULL, /* context (create one) */
+ idname, /* principal_name */
+ npwd, /* password */
+ NULL, /* ccache name (figure out the identity cc)*/
+ (krb5_deltat) d->tc_lifetime.current,
+ d->forwardable,
+ d->proxiable,
+ (krb5_deltat)((d->renewable)?d->tc_renew.current:0),
+ d->addressless, /* addressless */
+ d->publicIP, /* public IP */
+ NULL, /* prompter */
+ NULL /* prompter data */);
+
+ if (code) {
+ rv = KHM_ERROR_UNKNOWN;
+ goto _pwd_exit;
+ }
+
+ /* save the settings that we used for
+ obtaining the ticket. */
+ if (KHM_SUCCEEDED
+ (k5_open_config_handle(nc->identities[0],
+ KHM_FLAG_CREATE |
+ KCONF_FLAG_WRITEIFMOD,
+ &csp_idcfg))) {
+ k5_write_dlg_params(csp_idcfg, d);
+ khc_close_space(csp_idcfg);
+ }
+
+ /* and do a quick refresh of the krb5 tickets
+ so that other plug-ins that depend on krb5
+ can look up tickets inside NetIDMgr */
+ khm_krb5_list_tickets(&ctx);
+
+ /* if there was no default identity, we make
+ this one the default. */
+ kcdb_identity_refresh(nc->identities[0]);
+ {
+ khm_handle tdefault = NULL;
+
+ if (KHM_SUCCEEDED(kcdb_identity_get_default(&tdefault))) {
+ kcdb_identity_release(tdefault);
+ } else {
+ _reportf(L"There was no default identity. Setting defualt");
+ kcdb_identity_set_default(nc->identities[0]);
+ }
+ }
+
+ /* and then update the LRU too */
+ k5_update_LRU(nc->identities[0]);
+
+ if (ctx != NULL)
+ pkrb5_free_context(ctx);
+ }
/* result is only set when code != 0 */
if (code && result) {
diff --git a/src/windows/identity/plugins/krb5/krbconfig.csv b/src/windows/identity/plugins/krb5/krbconfig.csv
index b6754409e..205cbcb42 100644
--- a/src/windows/identity/plugins/krb5/krbconfig.csv
+++ b/src/windows/identity/plugins/krb5/krbconfig.csv
@@ -25,11 +25,13 @@ Krb5Cred,KC_SPACE,0,Kerberos V Credentials Provider
LRURealms,KC_STRING,,
LRUPrincipals,KC_STRING,,
LastDefaultIdent,KC_STRING,,Last known default identity
+ PromptCacheLifetime,KC_INT32,172800,Lifetime of the prompt cache in seconds
DefaultCCName,KC_STRING,,Default CC name (only per identity)
PromptCache,KC_SPACE,0,Cache of prompts (only per identity)
Name,KC_STRING,,
Banner,KC_STRING,,
PromptCount,KC_INT32,0,
+ ExpiresOn,KC_INT64,0,FILETIME of when the prompt cache is set to expire
(n),KC_SPACE,0,Parameters for each prompt
Prompt,KC_STRING,,
Type,KC_INT32,0,
diff --git a/src/windows/identity/plugins/krb5/lang/en_us/langres.rc b/src/windows/identity/plugins/krb5/lang/en_us/langres.rc
index aab909050..54f3ed787 100644
--- a/src/windows/identity/plugins/krb5/lang/en_us/langres.rc
+++ b/src/windows/identity/plugins/krb5/lang/en_us/langres.rc
@@ -382,7 +382,7 @@ BEGIN
IDS_NC_REALM "Realm"
IDS_KRB5_WARNING "Kerberos 5 Warning"
IDS_K5ERR_NAME_EXPIRED "<p><a id=""SwitchPanel"" param=""Krb5Cred""><b>Krb5</b></a><tab>: The selected principal name has expired.</p><p><tab> Please contact your system administrator.</p>"
- IDS_K5ERR_KEY_EXPIRED "<p><a id=""SwitchPanel"" param=""Krb5Cred""><b>Krb5</b></a><tab>: The password for the selected identity has expired.</p><p><tab> Click <a id=""Krb5Cred:Passwd"">here</a> to change the password</p>"
+ IDS_K5ERR_KEY_EXPIRED "<p><a id=""SwitchPanel"" param=""Krb5Cred""><b>Krb5</b></a><tab>: The password for the selected identity has expired.</p><p><tab> Click <a id=""Krb5Cred:!Passwd"">here</a> to change the password</p>"
IDS_KRB5_WARN_FMT "Kerberos 5: %s\n\n%s"
IDS_K5ERR_FMT "<p><a id=""SwitchPanel"" param=""Krb5Cred""><b>Krb5</b></a><tag>: %s</p>"
IDS_K5CFG_SHORT_DESC "Kerberos 5"
diff --git a/src/windows/identity/plugins/krb5/lang/krb5_msgs.mc b/src/windows/identity/plugins/krb5/lang/krb5_msgs.mc
index 01e01761f..cadc66626 100644
--- a/src/windows/identity/plugins/krb5/lang/krb5_msgs.mc
+++ b/src/windows/identity/plugins/krb5/lang/krb5_msgs.mc
@@ -158,6 +158,42 @@ Destroying Krb5 tickets
.
MessageId=
+SymbolicName=MSG_ERR_NETDOWN
+Language=English
+A network connection is unavailable
+.
+
+MessageId=
+SymbolicName=MSG_ERR_S_NETRETRY
+Language=English
+Please check your network connection or contact your network administrator for assistance.
+.
+
+MessageId=
+SymbolicName=MSG_ERR_TEMPDOWN
+Language=English
+A temporary network error caused the operation to fail
+.
+
+MessageId=
+SymbolicName=MSG_ERR_S_TEMPDOWN
+Language=English
+Please try again in a few minutes
+.
+
+MessageId=
+SymbolicName=MSG_ERR_NOHOST
+Language=English
+A server could not be reached
+.
+
+MessageId=
+SymbolicName=MSG_ERR_S_NOHOST
+Language=English
+This can be caused by the server being unavailable, network errors, or improper configuration. Please try again or contact your administrator for assistance.
+.
+
+MessageId=
SymbolicName=MSG_
Language=English
.