int main() { krb5_context context; krb5_authdata **results; krb5_authdata *container[2]; krb5_authdata **container_out; krb5_authdata **kdci; assert(krb5_init_context(&context) == 0); assert(krb5_merge_authdata(context, adseq1, adseq2, &results) == 0); compare_authdata(results[0], &ad1); compare_authdata( results[1], &ad2); compare_authdata(results[2], &ad4); compare_authdata( results[3], &ad3); assert(results[4] == NULL); krb5_free_authdata(context, results); container[0] = &ad3; container[1] = NULL; assert(krb5_encode_authdata_container( context, KRB5_AUTHDATA_IF_RELEVANT, container, &container_out) == 0); assert(krb5_find_authdata(context, adseq1, container_out, 22, &results) == 0); compare_authdata(&ad1, results[0]); compare_authdata( results[1], &ad4); compare_authdata( results[2], &ad3); assert( results[3] == NULL); krb5_free_authdata(context, container_out); assert(krb5_make_authdata_kdc_issued(context, &key, NULL, results, &kdci) == 0); assert(krb5_verify_authdata_kdc_issued(context, &key, kdci[0], NULL, &container_out) == 0); compare_authdata(container_out[0], results[0]); compare_authdata(container_out[1], results[1]); compare_authdata(container_out[2], results[2]); krb5_free_authdata(context, kdci); krb5_free_authdata(context, results); krb5_free_authdata(context, container_out); krb5_free_context(context); return 0; }
static kadm5_ret_t init_context(const char *client_name, const char *password, krb5_prompter_fct prompter, const char *keytab, krb5_ccache ccache, const char *service_name, kadm5_config_params *realm_params, unsigned long struct_version, unsigned long api_version, void **server_handle) { krb5_context context; kadm5_ret_t ret; kadm5_server_context *ctx; ret = krb5_init_context(&context); if (ret) return ret; ret = kadm5_c_init_with_context(context, client_name, password, prompter, keytab, ccache, service_name, realm_params, struct_version, api_version, server_handle); if(ret){ krb5_free_context(context); return ret; } ctx = *server_handle; ctx->my_context = 1; return 0; }
krb5_error_code krb5_afslog_uid_home(krb5_context context, krb5_ccache id, const char *cell, krb5_const_realm realm, uid_t uid, const char *homedir) { struct kafs_data kd; struct krb5_kafs_data d; krb5_error_code ret; kd.name = "krb5"; kd.afslog_uid = afslog_uid_int; kd.get_cred = get_cred; kd.get_realm = get_realm; kd.data = &d; if (context == NULL) { ret = krb5_init_context(&d.context); if (ret) return ret; } else d.context = context; if (id == NULL) { ret = krb5_cc_default(d.context, &d.id); if (ret) goto out; } else d.id = id; d.realm = realm; ret = afslog_uid_int(&kd, cell, 0, uid, homedir); if (id == NULL) krb5_cc_close(context, d.id); out: if (context == NULL) krb5_free_context(d.context); return ret; }
int main(int argc, char **argv) { krb5_context context; krb5_error_code ret; int i, optidx = 0; setprogname(argv[0]); if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) usage(1); if (help_flag) usage (0); if(version_flag){ print_version(NULL); exit(0); } argc -= optidx; argv += optidx; #ifdef MAKETICKET fooTicket(); #endif ret = krb5_init_context(&context); if (ret) errx (1, "krb5_init_context failed: %d", ret); for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) test_dh2key(context, i, &tests[i]); krb5_free_context(context); return 0; }
int main(int argc, char **argv) { krb5_context kcontext = NULL; krb5_keytab kt = NULL; krb5_keytab_entry entry; krb5_kt_cursor cursor = NULL; krb5_error_code krb5_err; int matched = 0; char svc_name[] = "host"; int svc_name_len = strlen (svc_name); krb5_err = krb5_init_context(&kcontext); if (krb5_err) { goto Error; } krb5_err = krb5_kt_default(kcontext, &kt); if (krb5_err) { goto Error; } krb5_err = krb5_kt_start_seq_get(kcontext, kt, &cursor); if (krb5_err) { goto Error; } while ((matched == 0) && (krb5_err = krb5_kt_next_entry(kcontext, kt, &entry, &cursor)) == 0) { krb5_data *nameData = krb5_princ_name (kcontext, entry.principal); if (NULL != nameData->data && svc_name_len == nameData->length && 0 == strncmp (svc_name, nameData->data, nameData->length)) { matched = 1; } krb5_free_keytab_entry_contents(kcontext, &entry); } krb5_err = krb5_kt_end_seq_get(kcontext, kt, &cursor); Error: if (NULL != kt) { krb5_kt_close (kcontext, kt); } if (NULL != kcontext) { krb5_free_context (kcontext); } // Return 0 if we got match or -1 if err or no match return (0 != krb5_err) ? -1 : matched ? 0 : -1; }
static int verify_creds() { krb5_context kcontext; krb5_ccache ccache; krb5_error_code kres; kres = krb5_init_context(&kcontext); if( kres == 0 ) { kres = krb5_cc_default( kcontext, &ccache ); if( kres == 0 ) { krb5_principal user_princ; kres = krb5_cc_get_principal( kcontext, ccache, &user_princ ); if( kres == 0 ) krb5_free_principal( kcontext, user_princ ); krb5_cc_close( kcontext, ccache ); } krb5_free_context(kcontext); } return kres; }
char *kerberos_login (char *user,char *authuser,int argc,char *argv[]) { krb5_context ctx; krb5_principal prnc; char kuser[NETMAXUSER]; char *ret = NIL; /* make a context */ if (!krb5_init_context (&ctx)) { /* build principal */ if (!krb5_parse_name (ctx,authuser,&prnc)) { /* can get local name for this principal? */ if (!krb5_aname_to_localname (ctx,prnc,NETMAXUSER-1,kuser)) { /* yes, local name permitted login as user? */ if (authserver_login (user,kuser,argc,argv) || authserver_login (lcase (user),kuser,argc,argv)) ret = myusername (); /* yes, return user name */ } krb5_free_principal (ctx,prnc); } krb5_free_context (ctx); /* finished with context */ } return ret; }
static PyObject * k5_c_valid_enctype(PyObject *self, PyObject *args) { char *name; krb5_context ctx; krb5_enctype type; krb5_error_code code; krb5_boolean valid; PyObject *ret; if (!PyArg_ParseTuple( args, "s", &name)) return NULL; code = krb5_init_context(&ctx); RETURN_ON_ERROR("krb5_init_context()", code); code = krb5_string_to_enctype(name, &type); RETURN_ON_ERROR("krb5_string_to_enctype()", code); valid = krb5_c_valid_enctype(type); ret = PyBool_FromLong((long) valid); krb5_free_context(ctx); return ret; }
/* * Called upon exit. Destroys machine credentials. */ void gssd_destroy_krb5_machine_creds(void) { krb5_context context; krb5_error_code code = 0; krb5_ccache ccache; struct gssd_k5_kt_princ *ple; char *k5err = NULL; code = krb5_init_context(&context); if (code) { k5err = gssd_k5_err_msg(NULL, code); printerr(0, "ERROR: %s while initializing krb5\n", k5err); goto out; } for (ple = gssd_k5_kt_princ_list; ple; ple = ple->next) { if (!ple->ccname) continue; if ((code = krb5_cc_resolve(context, ple->ccname, &ccache))) { k5err = gssd_k5_err_msg(context, code); printerr(0, "WARNING: %s while resolving credential " "cache '%s' for destruction\n", k5err, ple->ccname); continue; } if ((code = krb5_cc_destroy(context, ccache))) { k5err = gssd_k5_err_msg(context, code); printerr(0, "WARNING: %s while destroying credential " "cache '%s'\n", k5err, ple->ccname); } } out: free(k5err); krb5_free_context(context); }
DWORD LwKrb5GetDefaultCachePath( OUT PSTR* ppszCachePath ) { DWORD dwError = 0; PSTR pszCachePath = NULL; krb5_context ctx = NULL; const char *pszKrbDefault = NULL; krb5_error_code ret = 0; ret = krb5_init_context(&ctx); BAIL_ON_KRB_ERROR(ctx, ret); pszKrbDefault = krb5_cc_default_name(ctx); dwError = LwAllocateString( pszKrbDefault, &pszCachePath); BAIL_ON_LW_ERROR(dwError); *ppszCachePath = pszCachePath; cleanup: if (ctx) { krb5_free_context(ctx); } return dwError; error: *ppszCachePath = NULL; goto cleanup; }
static void krb5_init(void) { krb5_context context; krb5_error_code ret; krb5_boolean ret_val; ret = krb5_init_context(&context); if (ret) return; #if defined(AUTHENTICATION) && defined(FORWARD) krb5_appdefault_boolean(context, NULL, NULL, "forward", 0, &ret_val); if (ret_val) kerberos5_set_forward(1); krb5_appdefault_boolean(context, NULL, NULL, "forwardable", 0, &ret_val); if (ret_val) kerberos5_set_forwardable(1); #endif #ifdef ENCRYPTION krb5_appdefault_boolean(context, NULL, NULL, "encrypt", 0, &ret_val); if (ret_val) { encrypt_auto(1); decrypt_auto(1); wantencryption = 1; EncryptVerbose(1); } #endif krb5_free_context(context); }
static void test_mcc_default(void) { krb5_context context; krb5_error_code ret; krb5_ccache id, id2; int i; for (i = 0; i < 10; i++) { ret = krb5_init_context(&context); if (ret) krb5_err(context, 1, ret, "krb5_init_context"); ret = krb5_cc_set_default_name(context, "MEMORY:foo"); if (ret) krb5_err(context, 1, ret, "krb5_cc_set_default_name"); ret = krb5_cc_default(context, &id); if (ret) krb5_err(context, 1, ret, "krb5_cc_default"); ret = krb5_cc_default(context, &id2); if (ret) krb5_err(context, 1, ret, "krb5_cc_default"); ret = krb5_cc_close(context, id); if (ret) krb5_err(context, 1, ret, "krb5_cc_close"); ret = krb5_cc_close(context, id2); if (ret) krb5_err(context, 1, ret, "krb5_cc_close"); krb5_free_context(context); } }
int main(int argc, char **argv) { krb5_keyblock keyblock; krb5_error_code ret; krb5_context context; krb5_crypto crypto; int i; ret = krb5_init_context(&context); if (ret) errx(1, "krb5_context_init: %d", ret); ret = krb5_generate_random_keyblock(context, ENCTYPE_AES256_CTS_HMAC_SHA1_96, &keyblock); if (ret) krb5_err(context, 1, ret, "krb5_generate_random_keyblock"); ret = krb5_crypto_init(context, &keyblock, 0, &crypto); if (ret) krb5_err(context, 1, ret, "krb5_crypto_init"); test_special(context, crypto, 1, 60); test_special(context, crypto, 0, 60); for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { test_range(&tests[i], 1, context, crypto); test_range(&tests[i], 0, context, crypto); } krb5_free_keyblock_contents(context, &keyblock); krb5_crypto_destroy(context, crypto); krb5_free_context(context); return 0; }
static void finish_realm(kdc_realm_t *rdp) { if (rdp->realm_name) free(rdp->realm_name); if (rdp->realm_mpname) free(rdp->realm_mpname); if (rdp->realm_stash) free(rdp->realm_stash); if (rdp->realm_ports) free(rdp->realm_ports); if (rdp->realm_tcp_ports) free(rdp->realm_tcp_ports); if (rdp->realm_keytab) krb5_kt_close(rdp->realm_context, rdp->realm_keytab); if (rdp->realm_host_based_services) free(rdp->realm_host_based_services); if (rdp->realm_no_host_referral) free(rdp->realm_no_host_referral); if (rdp->realm_context) { if (rdp->realm_mprinc) krb5_free_principal(rdp->realm_context, rdp->realm_mprinc); if (rdp->realm_mkey.length && rdp->realm_mkey.contents) { /* XXX shouldn't memset be zap for safety? */ memset(rdp->realm_mkey.contents, 0, rdp->realm_mkey.length); free(rdp->realm_mkey.contents); } if (rdp->mkey_list) krb5_dbe_free_key_list(rdp->realm_context, rdp->mkey_list); krb5_db_fini(rdp->realm_context); if (rdp->realm_tgsprinc) krb5_free_principal(rdp->realm_context, rdp->realm_tgsprinc); krb5_free_context(rdp->realm_context); } memset(rdp, 0, sizeof(*rdp)); free(rdp); }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; int ival, val = 0; ret = krb5_init_context (&context); if (ret) errx (1, "krb5_init_context failed: %d", ret); val |= ival = string_to_key_test(context); if (ival && verbose) printf("string to key failed\n"); val |= ival = krb_enc_test(context); if (ival && verbose) printf("enc tests failed\n"); val |= ival = random_to_key(context); if (ival && verbose) printf("random to key failed\n"); val |= ival = iov_test(context); if (ival && verbose) printf("iov test failed\n"); if (verbose && val == 0) printf("all ok\n"); if (val) printf("tests failed\n"); krb5_free_context(context); return val; }
int main(int argc, char **argv) { krb5_context context; krb5_error_code ret; setprogname(argv[0]); ret = krb5_init_context(&context); if (ret) errx (1, "krb5_init_context failed: %d", ret); test_fcache_remove(context); test_default_name(context); test_mcache(context); test_init_vs_destroy(context, &krb5_mcc_ops); test_init_vs_destroy(context, &krb5_fcc_ops); test_mcc_default(); test_def_cc_name(context); krb5_free_context(context); return 0; }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_principal principal; ret = krb5_init_context(&context); if (ret) errx(1, "krb5_init_context"); ret = krb5_parse_name(context, "*****@*****.**", &principal); if (ret) krb5_err(context, ret, 1, "krb5_parse_name"); parse_file(context, principal, 0); parse_file(context, principal, 1); krb5_free_principal(context, principal); krb5_free_context(context); return 0; }
void krb5_cleanup_proc(void *context) { Authctxt *authctxt = (Authctxt *)context; debug("krb5_cleanup_proc called"); if (authctxt->krb5_fwd_ccache) { krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); authctxt->krb5_fwd_ccache = NULL; } if (authctxt->krb5_user) { krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user); authctxt->krb5_user = NULL; } if (authctxt->krb5_auth_ctx) { krb5_auth_con_free(authctxt->krb5_ctx, authctxt->krb5_auth_ctx); authctxt->krb5_auth_ctx = NULL; } if (authctxt->krb5_ctx) { krb5_free_context(authctxt->krb5_ctx); authctxt->krb5_ctx = NULL; } }
int main(int argc, char **argv) { krb5_context context; krb5_error_code ret; int i, optidx = 0; setprogname(argv[0]); if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) usage(1); if (help_flag) usage (0); if(version_flag){ print_version(NULL); exit(0); } argc -= optidx; argv += optidx; ret = krb5_init_context(&context); if (ret) errx (1, "krb5_init_context failed: %d", ret); for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { test_dh2key(i, context, &tests[i].X, NULL, NULL, tests[i].type, &tests[i].key); } krb5_free_context(context); return 0; }
static int krb5_detach(void *instance) { rlm_krb5_t *inst = instance; #ifndef HEIMDAL_KRB5 free(inst->vic_options); if (inst->gic_options) { krb5_get_init_creds_opt_free(*(inst->context), inst->gic_options); } #endif /* Don't free hostname, it's just a pointer into service_princ */ free(inst->service); if (inst->context) { krb5_free_context(*(inst->context)); } free(instance); return 0; }
int main() { size_t i; struct test *t; krb5_principal matching, princ; krb5_context ctx; if (krb5_init_context(&ctx) != 0) abort(); for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) { t = &tests[i]; if (t->matchstr != NULL) { if (krb5_parse_name(ctx, t->matchstr, &matching) != 0) abort(); if (t->non_host_nametype) matching->type = KRB5_NT_PRINCIPAL; else matching->type = KRB5_NT_SRV_HST; } else { matching = NULL; } if (krb5_parse_name(ctx, t->princstr, &princ) != 0) abort(); ctx->ignore_acceptor_hostname = t->ignore_acceptor_hostname; if (krb5_sname_match(ctx, matching, princ) != t->result) abort(); krb5_free_principal(ctx, matching); krb5_free_principal(ctx, princ); } krb5_free_context(ctx); return 0; }
static char * get_realm(void) { int error; krb5_context ctx; const char *msg; char *realm; error = krb5_init_context(&ctx); if (error) { smb_log_info("%s: Couldn't initialize kerberos: %d", ASL_LEVEL_DEBUG, __FUNCTION__, error); return (NULL); } error = krb5_get_default_realm(ctx, &realm); if (error) { msg = krb5_get_error_message(ctx, error); smb_log_info("%s: Couldn't get kerberos default realm: %s", ASL_LEVEL_DEBUG, __FUNCTION__, msg); krb5_free_error_message(ctx, msg); return (NULL); } krb5_free_context(ctx); return (realm); }
static PyObject * k5_cc_copy_creds(PyObject *self, PyObject *args) { krb5_context ctx; char *namein, *nameout; krb5_error_code code; krb5_ccache ccin, ccout; krb5_principal principal; if (!PyArg_ParseTuple( args, "ss", &namein, &nameout)) return NULL; code = krb5_init_context(&ctx); RETURN_ON_ERROR("krb5_init_context()", code); code = krb5_cc_resolve(ctx, namein, &ccin); RETURN_ON_ERROR("krb5_cc_resolve()", code); code = krb5_cc_get_principal(ctx, ccin, &principal); RETURN_ON_ERROR("krb5_cc_get_principal()", code); code = krb5_cc_resolve(ctx, nameout, &ccout); RETURN_ON_ERROR("krb5_cc_resolve()", code); code = krb5_cc_initialize(ctx, ccout, principal); RETURN_ON_ERROR("krb5_cc_get_initialize()", code); code = krb5_cc_copy_creds(ctx, ccin, ccout); RETURN_ON_ERROR("krb5_cc_copy_creds()", code); code = krb5_cc_close(ctx, ccin); RETURN_ON_ERROR("krb5_cc_close()", code); code = krb5_cc_close(ctx, ccout); RETURN_ON_ERROR("krb5_cc_close()", code); krb5_free_principal(ctx, principal); krb5_free_context(ctx); Py_INCREF(Py_None); return Py_None; }
krb5_error_code _gsskrb5_init (void) { krb5_error_code ret = 0; HEIMDAL_MUTEX_lock(&_gsskrb5_context_mutex); if(_gsskrb5_context == NULL) ret = krb5_init_context (&_gsskrb5_context); if (ret == 0 && !created_key) { HEIMDAL_key_create(&gssapi_context_key, gssapi_destroy_thread_context, ret); if (ret) { krb5_free_context(_gsskrb5_context); _gsskrb5_context = NULL; } else created_key = 1; } HEIMDAL_MUTEX_unlock(&_gsskrb5_context_mutex); return ret; }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_ccache ccache; krb5_principal principal = NULL; int optidx = 0; krb5_deltat ticket_life = 0; #ifdef HAVE_SIGACTION struct sigaction sa; #endif setprogname(argv[0]); setlocale(LC_ALL, ""); bindtextdomain("heimdal_kuser", HEIMDAL_LOCALEDIR); textdomain("heimdal_kuser"); ret = krb5_init_context(&context); if (ret == KRB5_CONFIG_BADFORMAT) errx(1, "krb5_init_context failed to parse configuration file"); else if (ret) errx(1, "krb5_init_context failed: %d", ret); if (getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) usage(1); if (help_flag) usage(0); if (version_flag) { print_version(NULL); exit(0); } argc -= optidx; argv += optidx; /* * Open the keytab now, we use the keytab to determine the principal's * realm when the requested principal has no realm. */ if (use_keytab || keytab_str) { if (keytab_str) ret = krb5_kt_resolve(context, keytab_str, &kt); else ret = krb5_kt_default(context, &kt); if (ret) krb5_err(context, 1, ret, "resolving keytab"); } if (pk_enterprise_flag) { ret = krb5_pk_enterprise_cert(context, pk_user_id, argv[0], &principal, &ent_user_id); if (ret) krb5_err(context, 1, ret, "krb5_pk_enterprise_certs"); pk_user_id = NULL; } else if (anonymous_flag) { ret = krb5_make_principal(context, &principal, argv[0], KRB5_WELLKNOWN_NAME, KRB5_ANON_NAME, NULL); if (ret) krb5_err(context, 1, ret, "krb5_make_principal"); krb5_principal_set_type(context, principal, KRB5_NT_WELLKNOWN); } else if (use_keytab || keytab_str) { get_princ_kt(context, &principal, argv[0]); } else { get_princ(context, &principal, argv[0]); } if (fcache_version) krb5_set_fcache_version(context, fcache_version); if (renewable_flag == -1) /* this seems somewhat pointless, but whatever */ krb5_appdefault_boolean(context, "kinit", krb5_principal_get_realm(context, principal), "renewable", FALSE, &renewable_flag); if (do_afslog == -1) krb5_appdefault_boolean(context, "kinit", krb5_principal_get_realm(context, principal), "afslog", TRUE, &do_afslog); if (cred_cache) ret = krb5_cc_resolve(context, cred_cache, &ccache); else { if (argc > 1) { char s[1024]; ret = krb5_cc_new_unique(context, NULL, NULL, &ccache); if (ret) krb5_err(context, 1, ret, "creating cred cache"); snprintf(s, sizeof(s), "%s:%s", krb5_cc_get_type(context, ccache), krb5_cc_get_name(context, ccache)); setenv("KRB5CCNAME", s, 1); } else { ret = krb5_cc_cache_match(context, principal, &ccache); if (ret) { const char *type; ret = krb5_cc_default(context, &ccache); if (ret) krb5_err(context, 1, ret, N_("resolving credentials cache", "")); /* * Check if the type support switching, and we do, * then do that instead over overwriting the current * default credential */ type = krb5_cc_get_type(context, ccache); if (krb5_cc_support_switch(context, type)) { krb5_cc_close(context, ccache); ret = get_switched_ccache(context, type, principal, &ccache); } } } } if (ret) krb5_err(context, 1, ret, N_("resolving credentials cache", "")); #ifndef NO_AFS if (argc > 1 && k_hasafs()) k_setpag(); #endif if (lifetime) { int tmp = parse_time(lifetime, "s"); if (tmp < 0) errx(1, N_("unparsable time: %s", ""), lifetime); ticket_life = tmp; } if (addrs_flag == 0 && extra_addresses.num_strings > 0) krb5_errx(context, 1, N_("specifying both extra addresses and " "no addresses makes no sense", "")); { int i; krb5_addresses addresses; memset(&addresses, 0, sizeof(addresses)); for(i = 0; i < extra_addresses.num_strings; i++) { ret = krb5_parse_address(context, extra_addresses.strings[i], &addresses); if (ret == 0) { krb5_add_extra_addresses(context, &addresses); krb5_free_addresses(context, &addresses); } } free_getarg_strings(&extra_addresses); } if (renew_flag || validate_flag) { ret = renew_validate(context, renew_flag, validate_flag, ccache, server_str, ticket_life); #ifndef NO_AFS if (ret == 0 && server_str == NULL && do_afslog && k_hasafs()) krb5_afslog(context, ccache, NULL, NULL); #endif exit(ret != 0); } ret = get_new_tickets(context, principal, ccache, ticket_life, 1); if (ret) exit(1); #ifndef NO_AFS if (ret == 0 && server_str == NULL && do_afslog && k_hasafs()) krb5_afslog(context, ccache, NULL, NULL); #endif if (argc > 1) { struct renew_ctx ctx; time_t timeout; timeout = ticket_lifetime(context, ccache, principal, server_str, NULL) / 2; ctx.context = context; ctx.ccache = ccache; ctx.principal = principal; ctx.ticket_life = ticket_life; ctx.timeout = timeout; #ifdef HAVE_SIGACTION memset(&sa, 0, sizeof(sa)); sigemptyset(&sa.sa_mask); sa.sa_handler = handle_siginfo; sigaction(SIGINFO, &sa, NULL); #endif ret = simple_execvp_timed(argv[1], argv+1, renew_func, &ctx, timeout); #define EX_NOEXEC 126 #define EX_NOTFOUND 127 if (ret == EX_NOEXEC) krb5_warnx(context, N_("permission denied: %s", ""), argv[1]); else if (ret == EX_NOTFOUND) krb5_warnx(context, N_("command not found: %s", ""), argv[1]); krb5_cc_destroy(context, ccache); #ifndef NO_AFS if (k_hasafs()) k_unlog(); #endif } else { krb5_cc_close(context, ccache); ret = 0; } krb5_free_principal(context, principal); if (kt) krb5_kt_close(context, kt); krb5_free_context(context); return ret; }
krb5_error_code KRB5_CALLCONV krb5_init_context_profile(profile_t profile, krb5_flags flags, krb5_context *context_out) { krb5_context ctx = 0; krb5_error_code retval; struct { krb5_timestamp now; krb5_int32 now_usec; long pid; } seed_data; krb5_data seed; int tmp; char *plugin_dir = NULL; /* Verify some assumptions. If the assumptions hold and the compiler is optimizing, this should result in no code being executed. If we're guessing "unsigned long long" instead of using uint64_t, the possibility does exist that we're wrong. */ { uint64_t i64; assert(sizeof(i64) == 8); i64 = 0, i64--, i64 >>= 62; assert(i64 == 3); i64 = 1, i64 <<= 31, i64 <<= 31, i64 <<= 1; assert(i64 != 0); i64 <<= 1; assert(i64 == 0); } retval = krb5int_initialize_library(); if (retval) return retval; #if (defined(_WIN32)) /* * Load the krbcc32.dll if necessary. We do this here so that * we know to use API: later on during initialization. * The context being NULL is ok. */ krb5_win_ccdll_load(ctx); /* * krb5_vercheck() is defined in win_glue.c, and this is * where we handle the timebomb and version server checks. */ retval = krb5_vercheck(); if (retval) return retval; #endif *context_out = NULL; ctx = calloc(1, sizeof(struct _krb5_context)); if (!ctx) return ENOMEM; ctx->magic = KV5M_CONTEXT; ctx->profile_secure = (flags & KRB5_INIT_CONTEXT_SECURE) != 0; retval = k5_os_init_context(ctx, profile, flags); if (retval) goto cleanup; ctx->trace_callback = NULL; #ifndef DISABLE_TRACING if (!ctx->profile_secure) k5_init_trace(ctx); #endif retval = get_boolean(ctx, KRB5_CONF_ALLOW_WEAK_CRYPTO, 0, &tmp); if (retval) goto cleanup; ctx->allow_weak_crypto = tmp; retval = get_boolean(ctx, KRB5_CONF_IGNORE_ACCEPTOR_HOSTNAME, 0, &tmp); if (retval) goto cleanup; ctx->ignore_acceptor_hostname = tmp; retval = get_tristate(ctx, KRB5_CONF_DNS_CANONICALIZE_HOSTNAME, "fallback", CANONHOST_FALLBACK, 1, &tmp); if (retval) goto cleanup; ctx->dns_canonicalize_hostname = tmp; /* initialize the prng (not well, but passable) */ if ((retval = krb5_c_random_os_entropy( ctx, 0, NULL)) !=0) goto cleanup; if ((retval = krb5_crypto_us_timeofday(&seed_data.now, &seed_data.now_usec))) goto cleanup; seed_data.pid = getpid (); seed.length = sizeof(seed_data); seed.data = (char *) &seed_data; if ((retval = krb5_c_random_add_entropy(ctx, KRB5_C_RANDSOURCE_TIMING, &seed))) goto cleanup; ctx->default_realm = 0; get_integer(ctx, KRB5_CONF_CLOCKSKEW, DEFAULT_CLOCKSKEW, &tmp); ctx->clockskew = tmp; /* DCE 1.1 and below only support CKSUMTYPE_RSA_MD4 (2) */ /* DCE add kdc_req_checksum_type = 2 to krb5.conf */ get_integer(ctx, KRB5_CONF_KDC_REQ_CHECKSUM_TYPE, CKSUMTYPE_RSA_MD5, &tmp); ctx->kdc_req_sumtype = tmp; get_integer(ctx, KRB5_CONF_AP_REQ_CHECKSUM_TYPE, 0, &tmp); ctx->default_ap_req_sumtype = tmp; get_integer(ctx, KRB5_CONF_SAFE_CHECKSUM_TYPE, CKSUMTYPE_RSA_MD5_DES, &tmp); ctx->default_safe_sumtype = tmp; get_integer(ctx, KRB5_CONF_KDC_DEFAULT_OPTIONS, KDC_OPT_RENEWABLE_OK, &tmp); ctx->kdc_default_options = tmp; #define DEFAULT_KDC_TIMESYNC 1 get_integer(ctx, KRB5_CONF_KDC_TIMESYNC, DEFAULT_KDC_TIMESYNC, &tmp); ctx->library_options = tmp ? KRB5_LIBOPT_SYNC_KDCTIME : 0; retval = profile_get_string(ctx->profile, KRB5_CONF_LIBDEFAULTS, KRB5_CONF_PLUGIN_BASE_DIR, 0, DEFAULT_PLUGIN_BASE_DIR, &plugin_dir); if (!retval) retval = k5_expand_path_tokens(ctx, plugin_dir, &ctx->plugin_base_dir); if (retval) { TRACE_PROFILE_ERR(ctx, KRB5_CONF_PLUGIN_BASE_DIR, KRB5_CONF_LIBDEFAULTS, retval); goto cleanup; } /* * We use a default file credentials cache of 3. See * lib/krb5/krb/ccache/file/fcc.h for a description of the * credentials cache types. * * Note: DCE 1.0.3a only supports a cache type of 1 * DCE 1.1 supports a cache type of 2. */ #define DEFAULT_CCACHE_TYPE 4 get_integer(ctx, KRB5_CONF_CCACHE_TYPE, DEFAULT_CCACHE_TYPE, &tmp); ctx->fcc_default_format = tmp + 0x0500; ctx->prompt_types = 0; ctx->use_conf_ktypes = 0; ctx->udp_pref_limit = -1; /* It's OK if this fails */ (void)profile_get_string(ctx->profile, KRB5_CONF_LIBDEFAULTS, KRB5_CONF_ERR_FMT, NULL, NULL, &ctx->err_fmt); *context_out = ctx; ctx = NULL; cleanup: profile_release_string(plugin_dir); krb5_free_context(ctx); return retval; }
/* * Get a ticket granting ticket and stuff it in the cache */ static const char * get_tgt( char * keytab_name, char * principal_name) { krb5_context context; krb5_error_code ret; krb5_principal client = NULL, server = NULL; krb5_creds creds; krb5_keytab keytab; krb5_ccache ccache; krb5_timestamp now; #ifdef KRB5_HEIMDAL_INCLUDES krb5_data tgtname = { KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME }; #else krb5_data tgtname = { 0, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME }; #endif static char *error = NULL; if (error != NULL) { amfree(error); error = NULL; } if ((ret = krb5_init_context(&context)) != 0) { error = vstrallocf(_("error initializing krb5 context: %s"), error_message(ret)); return (error); } /*krb5_init_ets(context);*/ if(!keytab_name) { error = vstrallocf(_("error -- no krb5 keytab defined")); return(error); } if(!principal_name) { error = vstrallocf(_("error -- no krb5 principal defined")); return(error); } /* * Resolve keytab file into a keytab object */ if ((ret = krb5_kt_resolve(context, keytab_name, &keytab)) != 0) { error = vstrallocf(_("error resolving keytab %s: %s"), keytab_name, error_message(ret)); return (error); } /* * Resolve the amanda service held in the keytab into a principal * object */ ret = krb5_parse_name(context, principal_name, &client); if (ret != 0) { error = vstrallocf(_("error parsing %s: %s"), principal_name, error_message(ret)); return (error); } #ifdef KRB5_HEIMDAL_INCLUDES ret = krb5_build_principal_ext(context, &server, krb5_realm_length(*krb5_princ_realm(context, client)), krb5_realm_data(*krb5_princ_realm(context, client)), tgtname.length, tgtname.data, krb5_realm_length(*krb5_princ_realm(context, client)), krb5_realm_data(*krb5_princ_realm(context, client)), 0); #else ret = krb5_build_principal_ext(context, &server, krb5_princ_realm(context, client)->length, krb5_princ_realm(context, client)->data, tgtname.length, tgtname.data, krb5_princ_realm(context, client)->length, krb5_princ_realm(context, client)->data, 0); #endif if (ret != 0) { error = vstrallocf(_("error while building server name: %s"), error_message(ret)); return (error); } ret = krb5_timeofday(context, &now); if (ret != 0) { error = vstrallocf(_("error getting time of day: %s"), error_message(ret)); return (error); } memset(&creds, 0, SIZEOF(creds)); creds.times.starttime = 0; creds.times.endtime = now + AMANDA_TKT_LIFETIME; creds.client = client; creds.server = server; /* * Get a ticket for the service, using the keytab */ ret = krb5_get_in_tkt_with_keytab(context, 0, NULL, NULL, NULL, keytab, 0, &creds, 0); if (ret != 0) { error = vstrallocf(_("error getting ticket for %s: %s"), principal_name, error_message(ret)); goto cleanup2; } if ((ret = krb5_cc_default(context, &ccache)) != 0) { error = vstrallocf(_("error initializing ccache: %s"), error_message(ret)); goto cleanup; } if ((ret = krb5_cc_initialize(context, ccache, client)) != 0) { error = vstrallocf(_("error initializing ccache: %s"), error_message(ret)); goto cleanup; } if ((ret = krb5_cc_store_cred(context, ccache, &creds)) != 0) { error = vstrallocf(_("error storing creds in ccache: %s"), error_message(ret)); /* FALLTHROUGH */ } krb5_cc_close(context, ccache); cleanup: krb5_free_cred_contents(context, &creds); cleanup2: #if 0 krb5_free_principal(context, client); krb5_free_principal(context, server); #endif krb5_free_context(context); return (error); }
int _GetSecurityObject(struct afscp_cell *cell) { int code = ENOENT; #ifdef HAVE_KERBEROS krb5_context context; krb5_creds match; krb5_creds *cred; krb5_ccache cc; char **realms, *realm; struct afsconf_cell celldata; char localcell[MAXCELLCHARS + 1]; struct rx_securityClass *sc; struct ktc_encryptionKey k; int i; rxkad_level l; code = _GetCellInfo(cell->name, &celldata); if (code != 0) { goto try_anon; } if (authas_name[0]) { code = _GetLocalSecurityObject(cell, authas_name, authas_inst); if (code == 0) { return 0; } } code = krb5_init_context(&context); /* see aklog.c main() */ if (code != 0) { goto try_anon; } if (cell->realm == NULL) { realm = NULL; code = krb5_get_host_realm(context, celldata.hostName[0], &realms); if (code == 0) { strlcpy(localcell, realms[0], sizeof(localcell)); krb5_free_host_realm(context, realms); realm = localcell; } else goto try_anon; } else { realm = cell->realm; strlcpy(localcell, realm, MAXCELLCHARS + 1); } if (realm) if (realm == NULL) { for (i = 0; (i < MAXCELLCHARS && cell->name[i]); i++) { if (isalpha(cell->name[i])) localcell[i] = toupper(cell->name[i]); else localcell[i] = cell->name[i]; } localcell[i] = '\0'; realm = localcell; } cc = NULL; code = krb5_cc_default(context, &cc); memset(&match, 0, sizeof(match)); Z_enctype(Z_credskey(&match)) = ENCTYPE_DES_CBC_CRC; if (code == 0) code = krb5_cc_get_principal(context, cc, &match.client); if (code == 0) code = krb5_build_principal(context, &match.server, strlen(realm), realm, "afs", cell->name, NULL); if (code != 0) { krb5_free_cred_contents(context, &match); if (cc) krb5_cc_close(context, cc); krb5_free_context(context); goto try_anon; } code = krb5_get_credentials(context, 0, cc, &match, &cred); if (code != 0) { krb5_free_principal(context, match.server); match.server = NULL; code = krb5_build_principal(context, &match.server, strlen(realm), realm, "afs", NULL); if (code == 0) code = krb5_get_credentials(context, 0, cc, &match, &cred); if (code != 0) { krb5_free_cred_contents(context, &match); if (cc) krb5_cc_close(context, cc); krb5_free_context(context); goto try_anon; } } if (insecure) l = rxkad_clear; else l = rxkad_crypt; memcpy(&k.data, Z_keydata(Z_credskey(cred)), 8); sc = (struct rx_securityClass *)rxkad_NewClientSecurityObject (l, &k, RXKAD_TKT_TYPE_KERBEROS_V5, cred->ticket.length, cred->ticket.data); krb5_free_creds(context, cred); krb5_free_cred_contents(context, &match); if (cc) krb5_cc_close(context, cc); krb5_free_context(context); cell->security = sc; cell->scindex = 2; return 0; try_anon: #endif /* HAVE_KERBEROS */ if (try_anonymous) return _GetNullSecurityObject(cell); else return code; }
void context_destroy(krb5ContextObject *self) { krb5_free_context(self->context); PyObject_Del( self ); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line arguments */ { int i; /* Looping var */ char *opt; /* Option character */ int fg; /* Run in the foreground */ int fds; /* Number of ready descriptors */ cupsd_client_t *con; /* Current client */ cupsd_job_t *job; /* Current job */ cupsd_listener_t *lis; /* Current listener */ time_t current_time, /* Current time */ activity, /* Client activity timer */ senddoc_time, /* Send-Document time */ expire_time, /* Subscription expire time */ report_time, /* Malloc/client/job report time */ event_time; /* Last event notification time */ long timeout; /* Timeout for cupsdDoSelect() */ struct rlimit limit; /* Runtime limit */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ #ifdef __sgi cups_file_t *fp; /* Fake lpsched lock file */ struct stat statbuf; /* Needed for checking lpsched FIFO */ #endif /* __sgi */ int run_as_child = 0; /* Needed for background fork/exec */ #ifdef __APPLE__ int use_sysman = !getuid(); /* Use system management functions? */ #else time_t netif_time = 0; /* Time since last network update */ #endif /* __APPLE__ */ #if HAVE_LAUNCHD int launchd_idle_exit; /* Idle exit on select timeout? */ #endif /* HAVE_LAUNCHD */ #ifdef HAVE_GETEUID /* * Check for setuid invocation, which we do not support! */ if (getuid() != geteuid()) { fputs("cupsd: Cannot run as a setuid program\n", stderr); return (1); } #endif /* HAVE_GETEUID */ /* * Check for command-line arguments... */ fg = 0; #ifdef HAVE_LAUNCHD if (getenv("CUPSD_LAUNCHD")) { Launchd = 1; fg = 1; } #endif /* HAVE_LAUNCHD */ for (i = 1; i < argc; i ++) if (argv[i][0] == '-') for (opt = argv[i] + 1; *opt != '\0'; opt ++) switch (*opt) { case 'C' : /* Run as child with config file */ run_as_child = 1; fg = -1; case 'c' : /* Configuration file */ i ++; if (i >= argc) { _cupsLangPuts(stderr, _("cupsd: Expected config filename " "after \"-c\" option.")); usage(1); } if (argv[i][0] == '/') { /* * Absolute directory... */ cupsdSetString(&ConfigurationFile, argv[i]); } else { /* * Relative directory... */ char *current; /* Current directory */ /* * Allocate a buffer for the current working directory to * reduce run-time stack usage; this approximates the * behavior of some implementations of getcwd() when they * are passed a NULL pointer. */ if ((current = malloc(1024)) == NULL) { _cupsLangPuts(stderr, _("cupsd: Unable to get current directory.")); return (1); } if (!getcwd(current, 1024)) { _cupsLangPuts(stderr, _("cupsd: Unable to get current directory.")); free(current); return (1); } cupsdSetStringf(&ConfigurationFile, "%s/%s", current, argv[i]); free(current); } break; case 'f' : /* Run in foreground... */ fg = 1; break; case 'F' : /* Run in foreground, but disconnect from terminal... */ fg = -1; break; case 'h' : /* Show usage/help */ usage(0); break; case 'l' : /* Started by launchd... */ #ifdef HAVE_LAUNCHD Launchd = 1; fg = 1; #else _cupsLangPuts(stderr, _("cupsd: launchd(8) support not compiled " "in, running in normal mode.")); fg = 0; #endif /* HAVE_LAUNCHD */ break; case 'p' : /* Stop immediately for profiling */ fputs("cupsd: -p (startup profiling) is for internal testing " "use only!\n", stderr); stop_scheduler = 1; fg = 1; break; case 'P' : /* Disable security profiles */ fputs("cupsd: -P (disable security profiles) is for internal " "testing use only!\n", stderr); UseProfiles = 0; break; #ifdef __APPLE__ case 'S' : /* Disable system management functions */ fputs("cupsd: -S (disable system management) for internal " "testing use only!\n", stderr); use_sysman = 0; break; #endif /* __APPLE__ */ case 't' : /* Test the cupsd.conf file... */ TestConfigFile = 1; fg = 1; break; default : /* Unknown option */ _cupsLangPrintf(stderr, _("cupsd: Unknown option \"%c\" - " "aborting."), *opt); usage(1); break; } else { _cupsLangPrintf(stderr, _("cupsd: Unknown argument \"%s\" - aborting."), argv[i]); usage(1); } if (!ConfigurationFile) cupsdSetString(&ConfigurationFile, CUPS_SERVERROOT "/cupsd.conf"); /* * If the user hasn't specified "-f", run in the background... */ if (!fg) { /* * Setup signal handlers for the parent... */ #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ sigset(SIGUSR1, parent_handler); sigset(SIGCHLD, parent_handler); sigset(SIGHUP, SIG_IGN); #elif defined(HAVE_SIGACTION) memset(&action, 0, sizeof(action)); sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGUSR1); action.sa_handler = parent_handler; sigaction(SIGUSR1, &action, NULL); sigaction(SIGCHLD, &action, NULL); sigemptyset(&action.sa_mask); action.sa_handler = SIG_IGN; sigaction(SIGHUP, &action, NULL); #else signal(SIGUSR1, parent_handler); signal(SIGCLD, parent_handler); signal(SIGHUP, SIG_IGN); #endif /* HAVE_SIGSET */ if (fork() > 0) { /* * OK, wait for the child to startup and send us SIGUSR1 or to crash * and the OS send us SIGCHLD... We also need to ignore SIGHUP which * might be sent by the init script to restart the scheduler... */ for (; parent_signal == 0;) sleep(1); if (parent_signal == SIGUSR1) return (0); if (wait(&i) < 0) { perror("cupsd"); return (1); } else if (WIFEXITED(i)) { fprintf(stderr, "cupsd: Child exited with status %d\n", WEXITSTATUS(i)); return (2); } else { fprintf(stderr, "cupsd: Child exited on signal %d\n", WTERMSIG(i)); return (3); } } #ifdef __OpenBSD__ /* * Call _thread_sys_closefrom() so the child process doesn't reset the * parent's file descriptors to be blocking. This is a workaround for a * limitation of userland libpthread on OpenBSD. */ _thread_sys_closefrom(0); #endif /* __OpenBSD__ */ /* * Since CoreFoundation and DBUS both create fork-unsafe data on execution of * a program, and since this kind of really unfriendly behavior seems to be * more common these days in system libraries, we need to re-execute the * background cupsd with the "-C" option to avoid problems. Unfortunately, * we also have to assume that argv[0] contains the name of the cupsd * executable - there is no portable way to get the real pathname... */ execlp(argv[0], argv[0], "-C", ConfigurationFile, (char *)0); exit(errno); } if (fg < 1) { /* * Make sure we aren't tying up any filesystems... */ chdir("/"); #ifndef DEBUG /* * Disable core dumps... */ getrlimit(RLIMIT_CORE, &limit); limit.rlim_cur = 0; setrlimit(RLIMIT_CORE, &limit); /* * Disconnect from the controlling terminal... */ setsid(); /* * Close all open files... */ getrlimit(RLIMIT_NOFILE, &limit); for (i = 0; i < limit.rlim_cur && i < 1024; i ++) close(i); /* * Redirect stdin/out/err to /dev/null... */ if ((i = open("/dev/null", O_RDONLY)) != 0) { dup2(i, 0); close(i); } if ((i = open("/dev/null", O_WRONLY)) != 1) { dup2(i, 1); close(i); } if ((i = open("/dev/null", O_WRONLY)) != 2) { dup2(i, 2); close(i); } #endif /* DEBUG */ } /* * Set the timezone info... */ tzset(); #ifdef LC_TIME setlocale(LC_TIME, ""); #endif /* LC_TIME */ /* * Set the maximum number of files... */ getrlimit(RLIMIT_NOFILE, &limit); #if !defined(HAVE_POLL) && !defined(HAVE_EPOLL) && !defined(HAVE_KQUEUE) if (limit.rlim_max > FD_SETSIZE) MaxFDs = FD_SETSIZE; else #endif /* !HAVE_POLL && !HAVE_EPOLL && !HAVE_KQUEUE */ #ifdef RLIM_INFINITY if (limit.rlim_max == RLIM_INFINITY) MaxFDs = 16384; else #endif /* RLIM_INFINITY */ MaxFDs = limit.rlim_max; limit.rlim_cur = MaxFDs; setrlimit(RLIMIT_NOFILE, &limit); cupsdStartSelect(); /* * Read configuration... */ if (!cupsdReadConfiguration()) { if (TestConfigFile) printf("%s contains errors\n", ConfigurationFile); else syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting!", ConfigurationFile); return (1); } else if (TestConfigFile) { printf("%s is OK\n", ConfigurationFile); return (0); } /* * Clean out old temp files and printer cache data. */ if (!strncmp(TempDir, RequestRoot, strlen(RequestRoot))) cupsdCleanFiles(TempDir, NULL); cupsdCleanFiles(CacheDir, "*.ipp"); #if HAVE_LAUNCHD if (Launchd) { /* * If we were started by launchd get the listen sockets file descriptors... */ launchd_checkin(); launchd_checkout(); } #endif /* HAVE_LAUNCHD */ /* * Startup the server... */ httpInitialize(); cupsdStartServer(); /* * Catch hangup and child signals and ignore broken pipes... */ #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ sigset(SIGCHLD, sigchld_handler); sigset(SIGHUP, sighup_handler); sigset(SIGPIPE, SIG_IGN); sigset(SIGTERM, sigterm_handler); #elif defined(HAVE_SIGACTION) memset(&action, 0, sizeof(action)); sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGTERM); sigaddset(&action.sa_mask, SIGCHLD); action.sa_handler = sigchld_handler; sigaction(SIGCHLD, &action, NULL); sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGHUP); action.sa_handler = sighup_handler; sigaction(SIGHUP, &action, NULL); sigemptyset(&action.sa_mask); action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &action, NULL); sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGTERM); sigaddset(&action.sa_mask, SIGCHLD); action.sa_handler = sigterm_handler; sigaction(SIGTERM, &action, NULL); #else signal(SIGCLD, sigchld_handler); /* No, SIGCLD isn't a typo... */ signal(SIGHUP, sighup_handler); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, sigterm_handler); #endif /* HAVE_SIGSET */ #ifdef __sgi /* * Try to create a fake lpsched lock file if one is not already there. * Some Adobe applications need it under IRIX in order to enable * printing... */ if ((fp = cupsFileOpen("/var/spool/lp/SCHEDLOCK", "w")) == NULL) { syslog(LOG_LPR, "Unable to create fake lpsched lock file " "\"/var/spool/lp/SCHEDLOCK\"\' - %s!", strerror(errno)); } else { fchmod(cupsFileNumber(fp), 0644); fchown(cupsFileNumber(fp), User, Group); cupsFileClose(fp); } #endif /* __sgi */ /* * Initialize authentication certificates... */ cupsdInitCerts(); /* * If we are running in the background, signal the parent process that * we are up and running... */ if (!fg || run_as_child) { /* * Send a signal to the parent process, but only if the parent is * not PID 1 (init). This avoids accidentally shutting down the * system on OpenBSD if you CTRL-C the server before it is up... */ i = getppid(); /* Save parent PID to avoid race condition */ if (i != 1) kill(i, SIGUSR1); } #ifdef __APPLE__ /* * Start power management framework... */ if (use_sysman) cupsdStartSystemMonitor(); #endif /* __APPLE__ */ /* * Send server-started event... */ #ifdef HAVE_LAUNCHD if (Launchd) cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL, "Scheduler started via launchd."); else #endif /* HAVE_LAUNCHD */ if (fg) cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL, "Scheduler started in foreground."); else cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL, "Scheduler started in background."); /* * Start any pending print jobs... */ cupsdCheckJobs(); /* * Loop forever... */ current_time = time(NULL); event_time = current_time; expire_time = current_time; fds = 1; report_time = 0; senddoc_time = current_time; while (!stop_scheduler) { /* * Check if there are dead children to handle... */ if (dead_children) process_children(); /* * Check if we need to load the server configuration file... */ if (NeedReload) { /* * Close any idle clients... */ if (cupsArrayCount(Clients) > 0) { for (con = (cupsd_client_t *)cupsArrayFirst(Clients); con; con = (cupsd_client_t *)cupsArrayNext(Clients)) if (con->http.state == HTTP_WAITING) cupsdCloseClient(con); else con->http.keep_alive = HTTP_KEEPALIVE_OFF; cupsdPauseListening(); } /* * Restart if all clients are closed and all jobs finished, or * if the reload timeout has elapsed... */ if ((cupsArrayCount(Clients) == 0 && (cupsArrayCount(PrintingJobs) == 0 || NeedReload != RELOAD_ALL)) || (time(NULL) - ReloadTime) >= ReloadTimeout) { /* * Shutdown the server... */ DoingShutdown = 1; cupsdStopServer(); /* * Read configuration... */ if (!cupsdReadConfiguration()) { syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting!", ConfigurationFile); break; } #if HAVE_LAUNCHD if (Launchd) { /* * If we were started by launchd, get the listen socket file * descriptors... */ launchd_checkin(); launchd_checkout(); } #endif /* HAVE_LAUNCHD */ /* * Startup the server... */ DoingShutdown = 0; cupsdStartServer(); /* * Send a server-restarted event... */ cupsdAddEvent(CUPSD_EVENT_SERVER_RESTARTED, NULL, NULL, "Scheduler restarted."); } } /* * Check for available input or ready output. If cupsdDoSelect() * returns 0 or -1, something bad happened and we should exit * immediately. * * Note that we at least have one listening socket open at all * times. */ if ((timeout = select_timeout(fds)) > 1 && LastEvent) timeout = 1; #if HAVE_LAUNCHD /* * If no other work is scheduled and we're being controlled by * launchd then timeout after 'LaunchdTimeout' seconds of * inactivity... */ if (timeout == 86400 && Launchd && LaunchdTimeout && !cupsArrayCount(ActiveJobs) && (!Browsing || !BrowseLocalProtocols || !cupsArrayCount(Printers))) { timeout = LaunchdTimeout; launchd_idle_exit = 1; } else launchd_idle_exit = 0; #endif /* HAVE_LAUNCHD */ if ((fds = cupsdDoSelect(timeout)) < 0) { /* * Got an error from select! */ #ifdef HAVE_DNSSD cupsd_printer_t *p; /* Current printer */ #endif /* HAVE_DNSSD */ if (errno == EINTR) /* Just interrupted by a signal */ continue; /* * Log all sorts of debug info to help track down the problem. */ cupsdLogMessage(CUPSD_LOG_EMERG, "cupsdDoSelect() failed - %s!", strerror(errno)); for (i = 0, con = (cupsd_client_t *)cupsArrayFirst(Clients); con; i ++, con = (cupsd_client_t *)cupsArrayNext(Clients)) cupsdLogMessage(CUPSD_LOG_EMERG, "Clients[%d] = %d, file = %d, state = %d", i, con->http.fd, con->file, con->http.state); for (i = 0, lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); lis; i ++, lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) cupsdLogMessage(CUPSD_LOG_EMERG, "Listeners[%d] = %d", i, lis->fd); cupsdLogMessage(CUPSD_LOG_EMERG, "CGIPipes[0] = %d", CGIPipes[0]); #ifdef __APPLE__ cupsdLogMessage(CUPSD_LOG_EMERG, "SysEventPipes[0] = %d", SysEventPipes[0]); #endif /* __APPLE__ */ for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs); job; job = (cupsd_job_t *)cupsArrayNext(ActiveJobs)) cupsdLogMessage(CUPSD_LOG_EMERG, "Jobs[%d] = %d < [%d %d] > [%d %d]", job->id, job->status_buffer ? job->status_buffer->fd : -1, job->print_pipes[0], job->print_pipes[1], job->back_pipes[0], job->back_pipes[1]); #ifdef HAVE_DNSSD for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); p; p = (cupsd_printer_t *)cupsArrayNext(Printers)) cupsdLogMessage(CUPSD_LOG_EMERG, "printer[%s] reg_name=\"%s\"", p->name, p->reg_name ? p->reg_name : "(null)"); #endif /* HAVE_DNSSD */ break; } current_time = time(NULL); /* * Write dirty config/state files... */ if (DirtyCleanTime && current_time >= DirtyCleanTime) cupsdCleanDirty(); #ifdef __APPLE__ /* * If we are going to sleep and still have pending jobs, stop them after * a period of time... */ if (SleepJobs > 0 && current_time >= SleepJobs && cupsArrayCount(PrintingJobs) > 0) { SleepJobs = 0; cupsdStopAllJobs(CUPSD_JOB_DEFAULT, 5); } #endif /* __APPLE__ */ #ifndef __APPLE__ /* * Update the network interfaces once a minute... */ if ((current_time - netif_time) >= 60) { netif_time = current_time; NetIFUpdate = 1; } #endif /* !__APPLE__ */ #if HAVE_LAUNCHD /* * If no other work was scheduled and we're being controlled by launchd * then timeout after 'LaunchdTimeout' seconds of inactivity... */ if (!fds && launchd_idle_exit) { cupsdLogMessage(CUPSD_LOG_INFO, "Printer sharing is off and there are no jobs pending, " "will restart on demand."); stop_scheduler = 1; break; } #endif /* HAVE_LAUNCHD */ /* * Resume listening for new connections as needed... */ if (ListeningPaused && ListeningPaused <= current_time && cupsArrayCount(Clients) < MaxClients) cupsdResumeListening(); /* * Expire subscriptions and unload completed jobs as needed... */ if (current_time > expire_time) { if (cupsArrayCount(Subscriptions) > 0) cupsdExpireSubscriptions(NULL, NULL); cupsdUnloadCompletedJobs(); expire_time = current_time; } #ifndef HAVE_AUTHORIZATION_H /* * Update the root certificate once every 5 minutes if we have client * connections... */ if ((current_time - RootCertTime) >= RootCertDuration && RootCertDuration && !RunUser && cupsArrayCount(Clients)) { /* * Update the root certificate... */ cupsdDeleteCert(0); cupsdAddCert(0, "root", NULL); } #endif /* !HAVE_AUTHORIZATION_H */ /* * Check for new data on the client sockets... */ for (con = (cupsd_client_t *)cupsArrayFirst(Clients); con; con = (cupsd_client_t *)cupsArrayNext(Clients)) { /* * Process pending data in the input buffer... */ if (con->http.used) { cupsdReadClient(con); continue; } /* * Check the activity and close old clients... */ activity = current_time - Timeout; if (con->http.activity < activity && !con->pipe_pid) { cupsdLogMessage(CUPSD_LOG_DEBUG, "Closing client %d after %d seconds of inactivity...", con->http.fd, Timeout); cupsdCloseClient(con); continue; } } /* * Update any pending multi-file documents... */ if ((current_time - senddoc_time) >= 10) { cupsdCheckJobs(); senddoc_time = current_time; } /* * Clean job history... */ if (JobHistoryUpdate && current_time >= JobHistoryUpdate) cupsdCleanJobs(); /* * Log statistics at most once a minute when in debug mode... */ if ((current_time - report_time) >= 60 && LogLevel >= CUPSD_LOG_DEBUG) { size_t string_count, /* String count */ alloc_bytes, /* Allocated string bytes */ total_bytes; /* Total string bytes */ #ifdef HAVE_MALLINFO struct mallinfo mem; /* Malloc information */ mem = mallinfo(); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: malloc-arena=%lu", mem.arena); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: malloc-used=%lu", mem.usmblks + mem.uordblks); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: malloc-free=%lu", mem.fsmblks + mem.fordblks); #endif /* HAVE_MALLINFO */ cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: clients=%d", cupsArrayCount(Clients)); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: jobs=%d", cupsArrayCount(Jobs)); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: jobs-active=%d", cupsArrayCount(ActiveJobs)); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: printers=%d", cupsArrayCount(Printers)); string_count = _cupsStrStatistics(&alloc_bytes, &total_bytes); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: stringpool-string-count=" CUPS_LLFMT, CUPS_LLCAST string_count); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: stringpool-alloc-bytes=" CUPS_LLFMT, CUPS_LLCAST alloc_bytes); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: stringpool-total-bytes=" CUPS_LLFMT, CUPS_LLCAST total_bytes); report_time = current_time; } /* * Handle OS-specific event notification for any events that have * accumulated. Don't send these more than once a second... */ if (LastEvent && (current_time - event_time) >= 1) { #ifdef HAVE_NOTIFY_POST if (LastEvent & (CUPSD_EVENT_PRINTER_ADDED | CUPSD_EVENT_PRINTER_DELETED | CUPSD_EVENT_PRINTER_MODIFIED)) { cupsdLogMessage(CUPSD_LOG_DEBUG2, "notify_post(\"com.apple.printerListChange\")"); notify_post("com.apple.printerListChange"); } if (LastEvent & CUPSD_EVENT_PRINTER_STATE_CHANGED) { cupsdLogMessage(CUPSD_LOG_DEBUG2, "notify_post(\"com.apple.printerHistoryChange\")"); notify_post("com.apple.printerHistoryChange"); } if (LastEvent & (CUPSD_EVENT_JOB_STATE_CHANGED | CUPSD_EVENT_JOB_CONFIG_CHANGED | CUPSD_EVENT_JOB_PROGRESS)) { cupsdLogMessage(CUPSD_LOG_DEBUG2, "notify_post(\"com.apple.jobChange\")"); notify_post("com.apple.jobChange"); } #endif /* HAVE_NOTIFY_POST */ /* * Reset the accumulated events... */ LastEvent = CUPSD_EVENT_NONE; event_time = current_time; } } /* * Log a message based on what happened... */ if (stop_scheduler) { cupsdLogMessage(CUPSD_LOG_INFO, "Scheduler shutting down normally."); cupsdAddEvent(CUPSD_EVENT_SERVER_STOPPED, NULL, NULL, "Scheduler shutting down normally."); } else { cupsdLogMessage(CUPSD_LOG_ERROR, "Scheduler shutting down due to program error."); cupsdAddEvent(CUPSD_EVENT_SERVER_STOPPED, NULL, NULL, "Scheduler shutting down due to program error."); } /* * Close all network clients... */ DoingShutdown = 1; cupsdStopServer(); #ifdef HAVE_LAUNCHD /* * Update the launchd KeepAlive file as needed... */ if (Launchd) launchd_checkout(); #endif /* HAVE_LAUNCHD */ /* * Stop all jobs... */ cupsdFreeAllJobs(); #ifdef __APPLE__ /* * Stop monitoring system event monitoring... */ if (use_sysman) cupsdStopSystemMonitor(); #endif /* __APPLE__ */ #ifdef HAVE_GSSAPI /* * Free the scheduler's Kerberos context... */ # ifdef __APPLE__ /* * If the weak-linked GSSAPI/Kerberos library is not present, don't try * to use it... */ if (krb5_init_context != NULL) # endif /* __APPLE__ */ if (KerberosContext) krb5_free_context(KerberosContext); #endif /* HAVE_GSSAPI */ #ifdef __sgi /* * Remove the fake IRIX lpsched lock file, but only if the existing * file is not a FIFO which indicates that the real IRIX lpsched is * running... */ if (!stat("/var/spool/lp/FIFO", &statbuf)) if (!S_ISFIFO(statbuf.st_mode)) unlink("/var/spool/lp/SCHEDLOCK"); #endif /* __sgi */ cupsdStopSelect(); return (!stop_scheduler); }