@@ -651,6 +651,107 @@ update_ldap_mod_auth_ind(krb5_context context, krb5_db_entry *entry,
651651 return ret ;
652652}
653653
654+ static krb5_error_code
655+ check_dn_in_container (krb5_context context , const char * dn ,
656+ char * const * subtrees , unsigned int ntrees )
657+ {
658+ unsigned int i ;
659+ size_t dnlen = strlen (dn ), stlen ;
660+
661+ for (i = 0 ; i < ntrees ; i ++ ) {
662+ if (subtrees [i ] == NULL || * subtrees [i ] == '\0' )
663+ return 0 ;
664+ stlen = strlen (subtrees [i ]);
665+ if (dnlen >= stlen &&
666+ strcasecmp (dn + dnlen - stlen , subtrees [i ]) == 0 &&
667+ (dnlen == stlen || dn [dnlen - stlen - 1 ] == ',' ))
668+ return 0 ;
669+ }
670+
671+ k5_setmsg (context , EINVAL , _ ("DN is out of the realm subtree" ));
672+ return EINVAL ;
673+ }
674+
675+ static krb5_error_code
676+ check_dn_exists (krb5_context context ,
677+ krb5_ldap_server_handle * ldap_server_handle ,
678+ const char * dn , krb5_boolean nonkrb_only )
679+ {
680+ krb5_error_code st = 0 , tempst ;
681+ krb5_ldap_context * ldap_context = context -> dal_handle -> db_context ;
682+ LDAP * ld = ldap_server_handle -> ldap_handle ;
683+ LDAPMessage * result = NULL , * ent ;
684+ char * attrs [] = { "krbticketpolicyreference" , "krbprincipalname" , NULL };
685+ char * * values ;
686+
687+ LDAP_SEARCH_1 (dn , LDAP_SCOPE_BASE , 0 , attrs , IGNORE_STATUS );
688+ if (st != LDAP_SUCCESS )
689+ return set_ldap_error (context , st , OP_SEARCH );
690+
691+ ent = ldap_first_entry (ld , result );
692+ CHECK_NULL (ent );
693+
694+ values = ldap_get_values (ld , ent , "krbticketpolicyreference" );
695+ if (values != NULL )
696+ ldap_value_free (values );
697+
698+ values = ldap_get_values (ld , ent , "krbprincipalname" );
699+ if (values != NULL ) {
700+ ldap_value_free (values );
701+ if (nonkrb_only ) {
702+ st = EINVAL ;
703+ k5_setmsg (context , st , _ ("ldap object is already kerberized" ));
704+ goto cleanup ;
705+ }
706+ }
707+
708+ cleanup :
709+ ldap_msgfree (result );
710+ return st ;
711+ }
712+
713+ static krb5_error_code
714+ validate_xargs (krb5_context context ,
715+ krb5_ldap_server_handle * ldap_server_handle ,
716+ const xargs_t * xargs , const char * standalone_dn ,
717+ char * const * subtrees , unsigned int ntrees )
718+ {
719+ krb5_error_code st ;
720+
721+ if (xargs -> dn != NULL ) {
722+ /* The supplied dn must be within a realm container. */
723+ st = check_dn_in_container (context , xargs -> dn , subtrees , ntrees );
724+ if (st )
725+ return st ;
726+ /* The supplied dn must exist without Kerberos attributes. */
727+ st = check_dn_exists (context , ldap_server_handle , xargs -> dn , TRUE);
728+ if (st )
729+ return st ;
730+ }
731+
732+ if (xargs -> linkdn != NULL ) {
733+ /* The supplied linkdn must be within a realm container. */
734+ st = check_dn_in_container (context , xargs -> linkdn , subtrees , ntrees );
735+ if (st )
736+ return st ;
737+ /* The supplied linkdn must exist. */
738+ st = check_dn_exists (context , ldap_server_handle , xargs -> linkdn ,
739+ FALSE);
740+ if (st )
741+ return st ;
742+ }
743+
744+ if (xargs -> containerdn != NULL && standalone_dn != NULL ) {
745+ /* standalone_dn (likely composed using containerdn) must be within a
746+ * container. */
747+ st = check_dn_in_container (context , standalone_dn , subtrees , ntrees );
748+ if (st )
749+ return st ;
750+ }
751+
752+ return 0 ;
753+ }
754+
654755krb5_error_code
655756krb5_ldap_put_principal (krb5_context context , krb5_db_entry * entry ,
656757 char * * db_args )
@@ -662,12 +763,12 @@ krb5_ldap_put_principal(krb5_context context, krb5_db_entry *entry,
662763 LDAPMessage * result = NULL , * ent = NULL ;
663764 char * * subtreelist = NULL ;
664765 char * user = NULL , * subtree = NULL , * principal_dn = NULL ;
665- char * * values = NULL , * strval [10 ]= {NULL }, errbuf [1024 ];
766+ char * strval [10 ]= {NULL }, errbuf [1024 ];
666767 char * filtuser = NULL ;
667768 struct berval * * bersecretkey = NULL ;
668769 LDAPMod * * mods = NULL ;
669770 krb5_boolean create_standalone = FALSE;
670- krb5_boolean krb_identity_exists = FALSE, establish_links = FALSE;
771+ krb5_boolean establish_links = FALSE;
671772 char * standalone_principal_dn = NULL ;
672773 krb5_tl_data * tl_data = NULL ;
673774 krb5_key_data * * keys = NULL ;
@@ -860,106 +961,17 @@ krb5_ldap_put_principal(krb5_context context, krb5_db_entry *entry,
860961 * any of the subtrees
861962 */
862963 if (xargs .dn_from_kbd == TRUE) {
863- /* make sure the DN falls in the subtree */
864- int dnlen = 0 , subtreelen = 0 ;
865- char * dn = NULL ;
866- krb5_boolean outofsubtree = TRUE;
867-
868- if (xargs .dn != NULL ) {
869- dn = xargs .dn ;
870- } else if (xargs .linkdn != NULL ) {
871- dn = xargs .linkdn ;
872- } else if (standalone_principal_dn != NULL ) {
873- /*
874- * Even though the standalone_principal_dn is constructed
875- * within this function, there is the containerdn input
876- * from the user that can become part of the it.
877- */
878- dn = standalone_principal_dn ;
879- }
880-
881964 /* Get the current subtree list if we haven't already done so. */
882965 if (subtreelist == NULL ) {
883966 st = krb5_get_subtree_info (ldap_context , & subtreelist , & ntrees );
884967 if (st )
885968 goto cleanup ;
886969 }
887970
888- for (tre = 0 ; tre < ntrees ; ++ tre ) {
889- if (subtreelist [tre ] == NULL || strlen (subtreelist [tre ]) == 0 ) {
890- outofsubtree = FALSE;
891- break ;
892- } else {
893- dnlen = strlen (dn );
894- subtreelen = strlen (subtreelist [tre ]);
895- if ((dnlen >= subtreelen ) && (strcasecmp ((dn + dnlen - subtreelen ), subtreelist [tre ]) == 0 )) {
896- outofsubtree = FALSE;
897- break ;
898- }
899- }
900- }
901-
902- if (outofsubtree == TRUE) {
903- st = EINVAL ;
904- k5_setmsg (context , st , _ ("DN is out of the realm subtree" ));
971+ st = validate_xargs (context , ldap_server_handle , & xargs ,
972+ standalone_principal_dn , subtreelist , ntrees );
973+ if (st )
905974 goto cleanup ;
906- }
907-
908- /*
909- * dn value will be set either by dn, linkdn or the standalone_principal_dn
910- * In the first 2 cases, the dn should be existing and in the last case we
911- * are supposed to create the ldap object. so the below should not be
912- * executed for the last case.
913- */
914-
915- if (standalone_principal_dn == NULL ) {
916- /*
917- * If the ldap object is missing, this results in an error.
918- */
919-
920- /*
921- * Search for krbprincipalname attribute here.
922- * This is to find if a kerberos identity is already present
923- * on the ldap object, in which case adding a kerberos identity
924- * on the ldap object should result in an error.
925- */
926- char * attributes []= {"krbticketpolicyreference" , "krbprincipalname" , NULL };
927-
928- ldap_msgfree (result );
929- result = NULL ;
930- LDAP_SEARCH_1 (dn , LDAP_SCOPE_BASE , 0 , attributes , IGNORE_STATUS );
931- if (st == LDAP_SUCCESS ) {
932- ent = ldap_first_entry (ld , result );
933- if (ent != NULL ) {
934- if ((values = ldap_get_values (ld , ent , "krbticketpolicyreference" )) != NULL ) {
935- ldap_value_free (values );
936- }
937-
938- if ((values = ldap_get_values (ld , ent , "krbprincipalname" )) != NULL ) {
939- krb_identity_exists = TRUE;
940- ldap_value_free (values );
941- }
942- }
943- } else {
944- st = set_ldap_error (context , st , OP_SEARCH );
945- goto cleanup ;
946- }
947- }
948- }
949-
950- /*
951- * If xargs.dn is set then the request is to add a
952- * kerberos principal on a ldap object, but if
953- * there is one already on the ldap object this
954- * should result in an error.
955- */
956-
957- if (xargs .dn != NULL && krb_identity_exists == TRUE) {
958- st = EINVAL ;
959- snprintf (errbuf , sizeof (errbuf ),
960- _ ("ldap object is already kerberized" ));
961- k5_setmsg (context , st , "%s" , errbuf );
962- goto cleanup ;
963975 }
964976
965977 if (xargs .linkdn != NULL ) {
0 commit comments