kadm5/kadmin: Add read-only mode
Now we can have read-only kadmind instances.
This commit is contained in:
@@ -149,12 +149,12 @@ void start_server(krb5_context, const char*);
|
||||
/* server.c */
|
||||
|
||||
krb5_error_code
|
||||
kadmind_loop (krb5_context, krb5_keytab, int);
|
||||
kadmind_loop (krb5_context, krb5_keytab, int, int);
|
||||
|
||||
/* rpc.c */
|
||||
|
||||
int
|
||||
handle_mit(krb5_context, void *, size_t, int);
|
||||
handle_mit(krb5_context, void *, size_t, int, int);
|
||||
|
||||
/* mod.c */
|
||||
|
||||
|
@@ -42,6 +42,7 @@ static char *keytab_str = sHDB;
|
||||
static int help_flag;
|
||||
static int version_flag;
|
||||
static int debug_flag;
|
||||
static int readonly_flag;
|
||||
static char *port_str;
|
||||
char *realm;
|
||||
|
||||
@@ -81,6 +82,8 @@ static struct getargs args[] = {
|
||||
},
|
||||
{ "ports", 'p', arg_string, &port_str,
|
||||
"ports to listen to", "port" },
|
||||
{ "read-only", 0, arg_flag, &readonly_flag,
|
||||
"read-only operations", NULL },
|
||||
{ "help", 'h', arg_flag, &help_flag, NULL, NULL },
|
||||
{ "version", 'v', arg_flag, &version_flag, NULL, NULL }
|
||||
};
|
||||
@@ -211,7 +214,7 @@ main(int argc, char **argv)
|
||||
if(realm)
|
||||
krb5_set_default_realm(context, realm); /* XXX */
|
||||
|
||||
kadmind_loop(context, keytab, sfd);
|
||||
kadmind_loop(context, keytab, sfd, readonly_flag);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
51
kadmin/rpc.c
51
kadmin/rpc.c
@@ -689,7 +689,7 @@ proc_init(kadm5_server_context *contextp,
|
||||
struct krb5_proc {
|
||||
const char *name;
|
||||
void (*func)(kadm5_server_context *, krb5_storage *, krb5_storage *);
|
||||
} procs[] = {
|
||||
} rwprocs[] = {
|
||||
{ "NULL", NULL },
|
||||
{ "create principal", proc_create_principal },
|
||||
{ "delete principal", proc_delete_principal },
|
||||
@@ -712,6 +712,29 @@ struct krb5_proc {
|
||||
{ "chpass principal v3", NULL },
|
||||
{ "chrand principal v3", NULL },
|
||||
{ "setkey principal v3", NULL }
|
||||
}, roprocs[] = {
|
||||
{ "NULL", NULL },
|
||||
{ "create principal", NULL },
|
||||
{ "delete principal", NULL },
|
||||
{ "modify principal", NULL },
|
||||
{ "rename principal", NULL },
|
||||
{ "get principal", proc_get_principal },
|
||||
{ "chpass principal", NULL },
|
||||
{ "chrand principal", NULL },
|
||||
{ "create policy", NULL },
|
||||
{ "delete policy", NULL },
|
||||
{ "modify policy", NULL },
|
||||
{ "get policy", NULL },
|
||||
{ "get privs", NULL },
|
||||
{ "init", NULL },
|
||||
{ "get principals", NULL },
|
||||
{ "get polices", NULL },
|
||||
{ "setkey principal", NULL },
|
||||
{ "setkey principal v4", NULL },
|
||||
{ "create principal v3", NULL },
|
||||
{ "chpass principal v3", NULL },
|
||||
{ "chrand principal v3", NULL },
|
||||
{ "setkey principal v3", NULL }
|
||||
};
|
||||
|
||||
static krb5_error_code
|
||||
@@ -742,8 +765,10 @@ struct gctx {
|
||||
|
||||
static int
|
||||
process_stream(krb5_context contextp,
|
||||
unsigned char *buf, size_t ilen,
|
||||
krb5_storage *sp)
|
||||
unsigned char *buf,
|
||||
size_t ilen,
|
||||
krb5_storage *sp,
|
||||
int readonly)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
krb5_storage *msg, *reply, *dreply;
|
||||
@@ -884,6 +909,7 @@ process_stream(krb5_context contextp,
|
||||
int conf_state;
|
||||
uint32_t seq;
|
||||
krb5_storage *sp1;
|
||||
struct krb5_proc *procs = readonly ? roprocs : rwprocs;
|
||||
|
||||
INSIST(gcred.service == rpg_privacy);
|
||||
|
||||
@@ -921,11 +947,16 @@ process_stream(krb5_context contextp,
|
||||
*/
|
||||
CHECK(krb5_store_uint32(dreply, gctx.seq_num));
|
||||
|
||||
if (chdr.proc >= sizeof(procs)/sizeof(procs[0])) {
|
||||
if (chdr.proc >= sizeof(rwprocs)/sizeof(rwprocs[0])) {
|
||||
krb5_warnx(contextp, "proc number out of array");
|
||||
} else if (procs[chdr.proc].func == NULL) {
|
||||
krb5_warnx(contextp, "proc '%s' never implemented",
|
||||
procs[chdr.proc].name);
|
||||
if (readonly && rwprocs[chdr.proc].func)
|
||||
krb5_warnx(contextp,
|
||||
"proc '%s' not allowed (readonly mode)",
|
||||
procs[chdr.proc].name);
|
||||
else
|
||||
krb5_warnx(contextp, "proc '%s' never implemented",
|
||||
procs[chdr.proc].name);
|
||||
} else {
|
||||
krb5_warnx(contextp, "proc %s", procs[chdr.proc].name);
|
||||
INSIST(server_handle != NULL);
|
||||
@@ -1101,7 +1132,11 @@ process_stream(krb5_context contextp,
|
||||
|
||||
|
||||
int
|
||||
handle_mit(krb5_context contextp, void *buf, size_t len, krb5_socket_t sock)
|
||||
handle_mit(krb5_context contextp,
|
||||
void *buf,
|
||||
size_t len,
|
||||
krb5_socket_t sock,
|
||||
int readonly)
|
||||
{
|
||||
krb5_storage *sp;
|
||||
|
||||
@@ -1110,7 +1145,7 @@ handle_mit(krb5_context contextp, void *buf, size_t len, krb5_socket_t sock)
|
||||
sp = krb5_storage_from_socket(sock);
|
||||
INSIST(sp != NULL);
|
||||
|
||||
process_stream(contextp, buf, len, sp);
|
||||
process_stream(contextp, buf, len, sp, readonly);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -40,7 +40,7 @@ static kadm5_ret_t check_aliases(kadm5_server_context *,
|
||||
|
||||
static kadm5_ret_t
|
||||
kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
|
||||
krb5_data *in, krb5_data *out)
|
||||
krb5_data *in, krb5_data *out, int readonly)
|
||||
{
|
||||
kadm5_ret_t ret;
|
||||
int32_t cmd, mask, kvno, tmp;
|
||||
@@ -139,8 +139,12 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
|
||||
}
|
||||
case kadm_delete:{
|
||||
op = "DELETE";
|
||||
if (readonly) {
|
||||
ret = KADM5_READ_ONLY;
|
||||
goto fail;
|
||||
}
|
||||
ret = krb5_ret_principal(sp, &princ);
|
||||
if(ret)
|
||||
if (ret)
|
||||
goto fail;
|
||||
krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name));
|
||||
krb5_warnx(contextp->context, "%s: %s %s", client, op, name);
|
||||
@@ -165,6 +169,10 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
|
||||
}
|
||||
case kadm_create:{
|
||||
op = "CREATE";
|
||||
if (readonly) {
|
||||
ret = KADM5_READ_ONLY;
|
||||
goto fail;
|
||||
}
|
||||
ret = kadm5_ret_principal_ent(sp, &ent);
|
||||
if(ret)
|
||||
goto fail;
|
||||
@@ -212,6 +220,10 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
|
||||
}
|
||||
case kadm_modify:{
|
||||
op = "MODIFY";
|
||||
if (readonly) {
|
||||
ret = KADM5_READ_ONLY;
|
||||
goto fail;
|
||||
}
|
||||
ret = kadm5_ret_principal_ent(sp, &ent);
|
||||
if(ret)
|
||||
goto fail;
|
||||
@@ -261,6 +273,10 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
|
||||
}
|
||||
case kadm_prune:{
|
||||
op = "PRUNE";
|
||||
if (readonly) {
|
||||
ret = KADM5_READ_ONLY;
|
||||
goto fail;
|
||||
}
|
||||
ret = krb5_ret_principal(sp, &princ);
|
||||
if (ret)
|
||||
goto fail;
|
||||
@@ -288,6 +304,10 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
|
||||
}
|
||||
case kadm_rename:{
|
||||
op = "RENAME";
|
||||
if (readonly) {
|
||||
ret = KADM5_READ_ONLY;
|
||||
goto fail;
|
||||
}
|
||||
ret = krb5_ret_principal(sp, &princ);
|
||||
if(ret)
|
||||
goto fail;
|
||||
@@ -335,6 +355,10 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
|
||||
krb5_boolean is_self_cpw, allow_self_cpw;
|
||||
|
||||
op = "CHPASS";
|
||||
if (readonly) {
|
||||
ret = KADM5_READ_ONLY;
|
||||
goto fail;
|
||||
}
|
||||
ret = krb5_ret_principal(sp, &princ);
|
||||
if (ret)
|
||||
goto fail;
|
||||
@@ -382,6 +406,10 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
|
||||
int n_key_data;
|
||||
|
||||
op = "CHPASS_WITH_KEY";
|
||||
if (readonly) {
|
||||
ret = KADM5_READ_ONLY;
|
||||
goto fail;
|
||||
}
|
||||
ret = krb5_ret_principal(sp, &princ);
|
||||
if(ret)
|
||||
goto fail;
|
||||
@@ -453,6 +481,10 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
|
||||
size_t i;
|
||||
|
||||
op = "RANDKEY";
|
||||
if (readonly) {
|
||||
ret = KADM5_READ_ONLY;
|
||||
goto fail;
|
||||
}
|
||||
ret = krb5_ret_principal(sp, &princ);
|
||||
if (ret)
|
||||
goto fail;
|
||||
@@ -758,7 +790,8 @@ v5_loop (krb5_context contextp,
|
||||
krb5_auth_context ac,
|
||||
krb5_boolean initial,
|
||||
void *kadm_handlep,
|
||||
krb5_socket_t fd)
|
||||
krb5_socket_t fd,
|
||||
int readonly)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
krb5_data in, out;
|
||||
@@ -773,7 +806,7 @@ v5_loop (krb5_context contextp,
|
||||
if(ret)
|
||||
krb5_err(contextp, 1, ret, "krb5_read_priv_message");
|
||||
doing_useful_work = 1;
|
||||
ret = kadmind_dispatch(kadm_handlep, initial, &in, &out);
|
||||
ret = kadmind_dispatch(kadm_handlep, initial, &in, &out, readonly);
|
||||
if (ret)
|
||||
krb5_err(contextp, 1, ret, "kadmind_dispatch");
|
||||
krb5_data_free(&in);
|
||||
@@ -798,7 +831,8 @@ match_appl_version(const void *data, const char *appl_version)
|
||||
static void
|
||||
handle_v5(krb5_context contextp,
|
||||
krb5_keytab keytab,
|
||||
krb5_socket_t fd)
|
||||
krb5_socket_t fd,
|
||||
int readonly)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
krb5_ticket *ticket;
|
||||
@@ -853,13 +887,14 @@ handle_v5(krb5_context contextp,
|
||||
&kadm_handlep);
|
||||
if(ret)
|
||||
krb5_err (contextp, 1, ret, "kadm5_init_with_password_ctx");
|
||||
v5_loop (contextp, ac, initial, kadm_handlep, fd);
|
||||
v5_loop (contextp, ac, initial, kadm_handlep, fd, readonly);
|
||||
}
|
||||
|
||||
krb5_error_code
|
||||
kadmind_loop(krb5_context contextp,
|
||||
krb5_keytab keytab,
|
||||
krb5_socket_t sock)
|
||||
krb5_socket_t sock,
|
||||
int readonly)
|
||||
{
|
||||
u_char buf[sizeof(KRB5_SENDAUTH_VERSION) + 4];
|
||||
ssize_t n;
|
||||
@@ -881,14 +916,14 @@ kadmind_loop(krb5_context contextp,
|
||||
krb5_errx (contextp, 1, "EOF reading sendauth version");
|
||||
|
||||
if(memcmp(buf + 4, KRB5_SENDAUTH_VERSION, len) == 0) {
|
||||
handle_v5(contextp, keytab, sock);
|
||||
handle_v5(contextp, keytab, sock, readonly);
|
||||
return 0;
|
||||
}
|
||||
len += 4;
|
||||
} else
|
||||
len = 4;
|
||||
|
||||
handle_mit(contextp, buf, len, sock);
|
||||
handle_mit(contextp, buf, len, sock, readonly);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user