Kadmin.c revision 54925bf60766fbb4f1f2d7c843721406a7b7a3fb
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <jni.h>
#include <adm_err.h>
#include <netdb.h>
#include <iconv.h>
#include <langinfo.h>
#include <clnt/client_internal.h>
#include <etypes.h>
kadm5_principal_ent_rec *, long *, char **, char **,
const char *, char *);
long *);
static int format_comments(kadm5_principal_ent_rec *, long *, char *);
static int extract_comments(kadm5_principal_ent_rec *, char **);
static void handle_error(JNIEnv *, int);
static void *server_handle = NULL;
static char *
{
char *fullname;
int len;
if (fullname)
return (fullname);
}
/*
* Class: Kadmin
* Method: sessionInit
* Signature:
*/
/*ARGSUSED*/
{
int cport = 749;
char *ka_service = NULL;
char *codeset;
int len;
if (server_handle != NULL)
/* fprintf(stderr, "codeset returned %s\n", codeset); XXX */
}
/* Get hold of string arguments */
if (!cname) {
goto err;
}
if (!cpasswd) {
goto err;
}
if (!crealm) {
goto err;
}
if (cur_realm)
if (!cserver) {
goto err;
}
if (port != 0)
else {
/*
* Look for a services map entry
* Note that this will be in network byte order,
* and that the API requires native byte order.
*/
if (rec)
}
/*
* Build kadm5_config_params with realm name and server name
*/
if (!ka_service) {
ret = KADM_ENOMEM;
goto err;
}
if (!ka_name) {
ret = KADM_ENOMEM;
goto err;
}
/* Release string arguments and variables */
if (cname)
if (cpasswd)
if (crealm)
if (cserver)
if (ka_name)
if (ka_service)
err:
if (ret) {
return (JNI_FALSE);
}
return (JNI_TRUE);
}
/*
* Class: Kadmin
* Method: sessionExit
* Signature: ()V
*/
/*ARGSUSED*/
{
/*
* Use persistant handle to close
*/
if (ret)
if (cur_realm) {
}
}
/*
* Class: Kadmin
* Method: getPrivs
* Signature: ()I
*/
/*ARGSUSED*/
{
long privs = 0;
/*
* Get ACL for this user
*/
if (ret)
return (privs);
}
static int
charcmp(const void *a, const void *b)
{
char **sa = (char **)a;
char **sb = (char **)b;
}
/*
* Class: Kadmin
* Method: getEncList
*/
/*ARGSUSED*/
{
jstring s;
return (NULL);
}
/*
* Create and populate a Java String array
*/
if (!stringclass) {
return (NULL);
}
if (!elist) {
return (NULL);
}
/*
* Populate groupings for encryption types that are similar.
*/
return (NULL);
}
for (i = 0; i < num_keysalts; grp[i] = i++);
for (i = 0; i < num_keysalts; i++) {
if (grp[i] != i)
continue;
for (j = i + 1; j < num_keysalts; j++) {
&similar)) {
return (NULL);
}
if (similar)
}
}
/*
* Populate from params' supported enc type list from the initial kadmin
* session, this is documented default that the client can handle.
*/
for (i = 0; i < num_keysalts; i++) {
for (j = 0; j < krb5_enctypes_length; j++) {
if (!s) {
return (NULL);
}
break;
}
}
}
return (elist);
}
/*
* Class: Kadmin
* Method: getPrincipalList
*/
/*ARGSUSED*/
{
jstring s;
char **princs;
int i, count;
/*
* Get the list
*/
if (ret) {
return (NULL);
}
/*
* Create and populate a Java String array
*/
if (!stringclass) {
return (NULL);
}
if (!plist) {
return (NULL);
}
for (i = 0; i < count; i++) {
if (!s) {
return (NULL);
}
}
return (plist);
}
/*
* Class: Kadmin
* Method: getPrincipalList2
*/
/*ARGSUSED*/
{
char **princs;
/*
* Get the list
*/
if (ret) {
return (NULL);
}
/*
* Build one large C string to hold list
*/
used = 0;
if (!princlist)
return (NULL);
for (i = 0; i < count; i++) {
if (!princlist)
return (NULL);
}
used += n + 1;
}
/*
* Create a Java String
*/
return (plist);
}
/*
* Class: Kadmin
* Method: loadPrincipal
*/
/*ARGSUSED*/
{
const char *cname;
char *fullname;
if (!cname) {
return (JNI_FALSE);
}
if (!fullname) {
return (JNI_FALSE);
}
/*
* Get the principal
*/
if (ret) {
return (JNI_FALSE);
}
if (ret) {
return (JNI_FALSE);
}
if (ret) {
return (JNI_FALSE);
}
/*
* Pull the comments out of the tl_data array
*/
if (ret) {
return (JNI_FALSE);
}
/*
* Fill in our Principal object
*/
if (ret) {
return (JNI_FALSE);
}
return (JNI_TRUE);
}
/*
* Class: Kadmin
* Method: savePrincipal
* Signature: (LPrincipal;)Z
*/
/*ARGSUSED*/
{
long mask;
/*
* Convert principal object to the kadmin API structure
*/
if (ret) {
return (JNI_FALSE);
}
/*
* Save the principal
*/
if (ret) {
goto out;
}
/*
* Handle any comments with read-modify-write
*/
if (ret) {
goto out;
}
/*
* Set the password if changed
*/
if (ret) {
goto out;
}
out:
return (ret);
}
/*
* Class: Kadmin
* Method: createPrincipal
* Signature: (LPrincipal;)Z
*/
/*ARGSUSED*/
{
long mask;
/*
* Convert principal object to the kadmin API structure
*/
if (ret) {
return (JNI_FALSE);
}
/*
* Create the new principal
*/
} else
if (ret) {
goto out;
}
/*
* Handle any comments with read-modify-write
*/
if (ret) {
goto out;
}
out:
return (ret);
}
/*
* Class: Kadmin
* Method: deletePrincipal
*/
/*ARGSUSED*/
{
const char *cname;
char *fullname;
/*
* Get name and call the delete function
*/
if (!cname) {
return (JNI_FALSE);
}
if (!fullname) {
return (JNI_FALSE);
}
if (ret) {
return (JNI_FALSE);
}
if (ret) {
return (JNI_FALSE);
}
if (ret) {
return (JNI_FALSE);
}
return (JNI_TRUE);
}
/*
* Class: Kadmin
* Method: getPolicyList
*/
/*ARGSUSED*/
{
jstring s;
char **pols;
int i, count;
/*
* Get the list
*/
if (ret) {
return (NULL);
}
/*
* Create and populate a Java String array
*/
if (!stringclass) {
return (NULL);
}
if (!plist) {
return (NULL);
}
for (i = 0; i < count; i++) {
if (!s) {
return (NULL);
}
}
return (plist);
}
/*
* Class: Kadmin
* Method: loadPolicy
*/
/*ARGSUSED*/
{
const char *cname;
if (!cname) {
return (JNI_FALSE);
}
if (ret) {
return (JNI_FALSE);
}
if (ret) {
return (JNI_FALSE);
}
return (JNI_TRUE);
}
/*
* Class: Kadmin
* Method: savePolicy
* Signature: (LPolicy;)Z
*/
/*ARGSUSED*/
{
long mask;
if (ret) {
return (JNI_FALSE);
}
if (ret) {
return (JNI_FALSE);
}
return (JNI_TRUE);
}
/*
* Class: Kadmin
* Method: createPolicy
* Signature: (LPolicy;)Z
*/
/*ARGSUSED*/
{
long mask;
if (ret) {
return (JNI_FALSE);
}
if (ret) {
return (JNI_FALSE);
}
return (JNI_TRUE);
}
/*
* Class: Kadmin
* Method: deletePolicy
*/
/*ARGSUSED*/
{
const char *cname;
if (!cname) {
return (JNI_FALSE);
}
if (ret) {
return (JNI_FALSE);
}
return (JNI_TRUE);
}
#ifdef needtoknowmore
/*
* Class: Kadmin
* Method: loadDefaults
* Signature: (LConfig;)Z
*/
/*ARGSUSED*/
{
/*
*
*/
return (JNI_TRUE);
}
/*
* Class: Kadmin
* Method: saveDefaults
* Signature: (LConfig;)Z
*/
/*ARGSUSED*/
{
/*
*
*/
return (JNI_TRUE);
}
#endif
static int
{
jstring s;
jfieldID f;
const char *str;
jlong l;
jint i;
jboolean b;
char *fullname;
*mask = 0;
if (!prcl)
return (KADM_JNI_CLASS);
if (!dateclass)
return (KADM_JNI_CLASS);
if (!intclass)
return (KADM_JNI_CLASS);
if (!f)
return (KADM_JNI_FIELD);
if (!obj)
return (KADM_JNI_OFIELD);
if (!str)
return (KADM_JNI_STRING);
if (!fullname)
return (KADM_ENOMEM);
if (ret)
return (ret);
if (ret)
return (ret);
if (new)
*mask |= KADM5_PRINCIPAL;
if (!f)
return (KADM_JNI_FIELD);
if (!obj)
return (KADM_JNI_OFIELD);
if (!mid)
return (KADM_JNI_METHOD);
p->princ_expire_time = (long)(l / 1000LL);
if (!f)
return (KADM_JNI_FIELD);
if (!obj)
return (KADM_JNI_OFIELD);
if (!str)
return (KADM_JNI_STRING);
if (ret) {
return (ret);
}
}
if (!f)
return (KADM_JNI_FIELD);
if (!obj)
return (KADM_JNI_OFIELD);
if (!str)
return (KADM_JNI_STRING);
if (!p->policy)
return (KADM_ENOMEM);
*mask |= KADM5_POLICY;
else if (!new)
*mask |= KADM5_POLICY_CLR;
if (!f)
return (KADM_JNI_FIELD);
if (obj) {
if (!mid)
return (KADM_JNI_METHOD);
p->pw_expiration = (long)(l / 1000LL);
*mask |= KADM5_PW_EXPIRATION;
}
if (!f)
return (KADM_JNI_FIELD);
if (!obj)
return (KADM_JNI_OFIELD);
if (!mid)
return (KADM_JNI_METHOD);
p->max_life = i;
*mask |= KADM5_MAX_LIFE;
if (!f)
return (KADM_JNI_FIELD);
if (!obj)
return (KADM_JNI_OFIELD);
if (!mid)
return (KADM_JNI_METHOD);
p->max_renewable_life = i;
*mask |= KADM5_MAX_RLIFE;
/*
* Comments: because of API rules on the TL_DATA entries,
* which say that a load-modify-write is always necessary,
* we will only deal with comments if they are newly changed.
*/
if (!f)
return (KADM_JNI_FIELD);
if (b == JNI_TRUE) {
if (!f)
return (KADM_JNI_FIELD);
if (!obj)
return (KADM_JNI_OFIELD);
if (!str)
return (KADM_JNI_STRING);
if (!*comments)
return (KADM_ENOMEM);
}
if (!f)
return (KADM_JNI_FIELD);
if (!obj)
return (KADM_JNI_OFIELD);
if (!mid)
return (KADM_JNI_METHOD);
p->kvno = i;
*mask |= KADM5_KVNO;
/*
* Get the Principal.flags field id
*/
"LFlags;");
if (!f)
return (KADM_JNI_FIELD);
/*
* Get the Principal.Flags object
*/
if (!obj)
return (KADM_JNI_OFIELD);
/*
* Get the Flags object's class
*/
if (!flagsClass)
return (KADM_JNI_CLASS);
/*
* Now get the Flags.flags field's value
*/
if (!f)
return (KADM_JNI_FIELD);
p->attributes = i & ~65536;
*mask |= KADM5_ATTRIBUTES;
if (!f)
return (KADM_JNI_FIELD);
if (!obj)
return (KADM_JNI_OFIELD);
if (!str)
return (KADM_JNI_STRING);
if (!*pw)
return (KADM_ENOMEM);
return (0);
}
static int
{
jstring s;
jfieldID f;
char *cstr;
if (!prcl)
return (KADM_JNI_CLASS);
if (!dateclass)
return (KADM_JNI_CLASS);
if (!intclass)
return (KADM_JNI_CLASS);
if (!f)
return (KADM_JNI_FIELD);
if (!s)
return (KADM_JNI_NEWSTRING);
if (!f)
return (KADM_JNI_FIELD);
if (!mid)
return (KADM_JNI_METHOD);
if (!obj)
return (KADM_JNI_OFIELD);
if (!f)
return (KADM_JNI_FIELD);
used = 0;
return (errno);
for (i = 0; i < p->n_key_data; i++) {
for (j = 0; j < krb5_enctypes_length; j++) {
if (key_data->key_data_type[0] ==
krb5_enctypes_list[j].etype) {
return (errno);
}
i_str);
/*
* We reallocate if existing + what we need +
* 2 (the null byte and a space for the list).
*/
size += 2048);
return (errno);
}
}
used += n + 1;
break;
}
}
}
if (!s)
return (KADM_JNI_NEWSTRING);
if (!f)
return (KADM_JNI_FIELD);
if (!cstr)
return (KADM_ENOMEM);
if (!s)
return (KADM_JNI_NEWSTRING);
if (!f)
return (KADM_JNI_FIELD);
if (!mid)
return (KADM_JNI_METHOD);
if (!obj)
return (KADM_JNI_OFIELD);
if (!f)
return (KADM_JNI_FIELD);
if (!mid)
return (KADM_JNI_METHOD);
if (!obj)
return (KADM_JNI_OFIELD);
if (!f)
return (KADM_JNI_FIELD);
if (!mid)
return (KADM_JNI_METHOD);
if (!obj)
return (KADM_JNI_OBJECT);
if (!f)
return (KADM_JNI_FIELD);
if (!mid)
return (KADM_JNI_METHOD);
(jint) p->max_renewable_life);
if (!obj)
return (KADM_JNI_OBJECT);
if (!f)
return (KADM_JNI_FIELD);
if (!mid)
return (KADM_JNI_METHOD);
if (!obj)
return (KADM_JNI_OFIELD);
if (ret)
return (ret);
if (ret)
return (ret);
if (!f)
return (KADM_JNI_FIELD);
if (!s)
return (KADM_JNI_NEWSTRING);
if (!f)
return (KADM_JNI_FIELD);
if (!mid)
return (KADM_JNI_METHOD);
if (!obj)
return (KADM_JNI_OFIELD);
if (!f)
return (KADM_JNI_FIELD);
if (!mid)
return (KADM_JNI_METHOD);
if (!obj)
return (KADM_JNI_OFIELD);
if (!f)
return (KADM_JNI_FIELD);
if (!mid)
return (KADM_JNI_METHOD);
(jint) p->fail_auth_count);
if (!obj)
return (KADM_JNI_OBJECT);
if (!f)
return (KADM_JNI_FIELD);
if (!cstr)
return (KADM_ENOMEM);
if (!s)
return (KADM_JNI_NEWSTRING);
if (!f)
return (KADM_JNI_FIELD);
if (!mid)
return (KADM_JNI_METHOD);
if (!obj)
return (KADM_JNI_OBJECT);
if (!f)
return (KADM_JNI_FIELD);
if (!mid)
return (KADM_JNI_METHOD);
if (!obj)
return (KADM_JNI_OBJECT);
i = p->attributes;
/*
* Get the Principal.flags field id
*/
"LFlags;");
if (!f)
return (KADM_JNI_FIELD);
/*
* Get the Principal.Flags object
*/
if (!obj)
return (KADM_JNI_OFIELD);
/*
* Get the Flags object's class
*/
/*
* Now set the Flags.flags field's value
*/
if (!f)
return (KADM_JNI_FIELD);
return (0);
}
static int
kadm5_policy_ent_rec *p, long *mask)
{
jstring s;
jfieldID f;
const char *str;
int i;
*mask = 0;
if (!pocl)
return (KADM_JNI_CLASS);
if (!intclass)
return (KADM_JNI_CLASS);
if (!f)
return (KADM_JNI_FIELD);
if (!obj)
return (KADM_JNI_OFIELD);
if (!str)
return (KADM_JNI_STRING);
if (!p->policy)
return (KADM_ENOMEM);
if (new)
*mask |= KADM5_POLICY;
if (!f)
return (KADM_JNI_FIELD);
if (!obj)
return (KADM_JNI_OFIELD);
if (!mid)
return (KADM_JNI_METHOD);
p->pw_min_life = i;
*mask |= KADM5_PW_MIN_LIFE;
if (!f)
return (KADM_JNI_FIELD);
if (!obj)
return (KADM_JNI_OFIELD);
if (!mid)
return (KADM_JNI_METHOD);
p->pw_max_life = i;
*mask |= KADM5_PW_MAX_LIFE;
if (!f)
return (KADM_JNI_FIELD);
if (!obj)
return (KADM_JNI_OFIELD);
if (!mid)
return (KADM_JNI_METHOD);
p->pw_min_length = i;
*mask |= KADM5_PW_MIN_LENGTH;
if (!f)
return (KADM_JNI_FIELD);
if (!obj)
return (KADM_JNI_OFIELD);
if (!mid)
return (KADM_JNI_METHOD);
p->pw_min_classes = i;
*mask |= KADM5_PW_MIN_CLASSES;
if (!f)
return (KADM_JNI_FIELD);
if (!obj)
return (KADM_JNI_OFIELD);
if (!mid)
return (KADM_JNI_METHOD);
p->pw_history_num = i;
*mask |= KADM5_PW_HISTORY_NUM;
return (0);
}
static int
{
jstring s;
jfieldID f;
if (!pocl)
return (KADM_JNI_CLASS);
if (!intclass)
return (KADM_JNI_CLASS);
if (!f)
return (KADM_JNI_FIELD);
if (!s)
return (KADM_JNI_NEWSTRING);
if (!f)
return (KADM_JNI_FIELD);
if (!mid)
return (KADM_JNI_METHOD);
if (!obj)
return (KADM_JNI_OBJECT);
if (!f)
return (KADM_JNI_FIELD);
if (!mid)
return (KADM_JNI_METHOD);
if (!obj)
return (KADM_JNI_OBJECT);
if (!f)
return (KADM_JNI_FIELD);
if (!mid)
return (KADM_JNI_METHOD);
if (!obj)
return (KADM_JNI_OBJECT);
if (!f)
return (KADM_JNI_FIELD);
if (!mid)
return (KADM_JNI_METHOD);
if (!obj)
return (KADM_JNI_OBJECT);
if (!f)
return (KADM_JNI_FIELD);
if (!mid)
return (KADM_JNI_METHOD);
if (!obj)
return (KADM_JNI_OBJECT);
if (!f)
return (KADM_JNI_FIELD);
if (!mid)
return (KADM_JNI_METHOD);
if (!obj)
return (KADM_JNI_OBJECT);
return (0);
}
#define SUNSOFT_COMMENTS 256
/*
* The new principal has been saved; now we do a load-modify-store
* to get the comments into the TL_DATA array.
*/
static int
{
return (0);
if (ret)
return (ret);
mask = 0;
if (ret)
return (ret);
if (mask) {
if (ret)
return (ret);
}
return (0);
}
/*
* Put the comments into TL_DATA.
*/
static int
{
char *s;
return (0);
if (!tdp)
return (KADM_ENOMEM);
if (!s)
return (KADM_ENOMEM);
/*
* Search for existing comments field, or find next-to-last
*/
if (t->tl_data_type == SUNSOFT_COMMENTS)
break;
if (t) {
free(t->tl_data_contents);
t->tl_data_contents = (krb5_octet *)s;
} else {
if (t1)
else
p->n_tl_data++;
}
*mask |= KADM5_TL_DATA;
return (0);
}
/*
* The principal has been loaded, so we pluck the comments out of TL_DATA.
*/
static int
{
krb5_tl_data *t;
char *s;
/*
* Search for existing comments field, or find next-to-last
*/
if (!p->n_tl_data)
return (0);
for (t = p->tl_data; t; t = t->tl_data_next)
if (t->tl_data_type == SUNSOFT_COMMENTS)
break;
if (t && t->tl_data_length) {
s = strdup((char *)t->tl_data_contents);
if (!s)
return (KADM_ENOMEM);
s[t->tl_data_length] = 0;
*comments = s;
}
return (0);
}
/*
* Set password for the modified principal
*/
static int
{
int keepold = 0;
return (0);
else
if (ret)
return (ret);
return (0);
}
static void
{
char *s;
char *tptr;
const char *fptr;
s = (char *)error_message(error);
/* fprintf(stderr, "Kadmin: %s (%d)\n", s, error); XXX */
s = to;
/* fprintf(stderr, "Kadmin: %s (%d)\n", s, error); XXX */
}
}
(const char *)s);
}