Revision 951
Added by Jing Tao almost 23 years ago
src/edu/ucsb/nceas/metacat/AccessControlList.java | ||
---|---|---|
58 | 58 |
private static final int WRITE = 2; |
59 | 59 |
private static final int READ = 4; |
60 | 60 |
private static final int ALL = 7; |
61 |
private static final String ALLOWFIRST="allowFirst"; |
|
62 |
private static final String DENYFIRST="denyFirst"; |
|
63 |
private static final String ALLOW="allow"; |
|
64 |
private static final String DENY="deny"; |
|
65 |
private static final String PUBLIC="public"; |
|
61 | 66 |
private static String sysdate = MetaCatUtil.dbAdapter.getDateTimeFunction(); |
62 | 67 |
private static String isnull = MetaCatUtil.dbAdapter.getIsNULLFunction(); |
63 | 68 |
|
... | ... | |
545 | 550 |
return txtPerm.append("\"").toString(); |
546 | 551 |
} |
547 | 552 |
|
553 |
|
|
548 | 554 |
/** |
555 |
* Check if a document id is a access document. Access document need user |
|
556 |
* has "all" permission to access it. |
|
557 |
* @param docId, the document id need to be checked |
|
558 |
*/ |
|
559 |
private boolean isAccessDocument(String docId) throws SQLException |
|
560 |
{ |
|
561 |
//detele the rev number if docid contains it |
|
562 |
docId=MetaCatUtil.getDocIdFromString(docId); |
|
563 |
PreparedStatement pStmt=null; |
|
564 |
try |
|
565 |
{ |
|
566 |
pStmt = conn.prepareStatement("select 'x' from xml_access where " + |
|
567 |
"accessfileid like '" + docId + "'"); |
|
568 |
pStmt.execute(); |
|
569 |
ResultSet rs = pStmt.getResultSet(); |
|
570 |
boolean hasRow = rs.next(); |
|
571 |
pStmt.close(); |
|
572 |
if(hasRow) |
|
573 |
{ |
|
574 |
return true; |
|
575 |
} |
|
576 |
} |
|
577 |
catch(SQLException e) |
|
578 |
{ |
|
579 |
pStmt.close(); |
|
580 |
throw new SQLException("AccessControlList.hasPermission():2 " + |
|
581 |
"Error checking ownership for " + principal + |
|
582 |
" on document #" + docId + ". " + e.getMessage()); |
|
583 |
} |
|
584 |
return false; |
|
585 |
}//isAccessDocument |
|
586 |
|
|
587 |
/** |
|
588 |
* To create a part of query: "docid like '" +str1+ "', " +"docid like '" |
|
589 |
* +str2+"'" ... We need to check user, group and public together for the |
|
590 |
* permission. So we need the principal in an array and according the array |
|
591 |
* to create a part of query which will be used in other methods |
|
592 |
* @param principals, a string array storing the username, groups name and |
|
593 |
* public. |
|
594 |
*/ |
|
595 |
private String partQueryAboutDocId( String [] principals) |
|
596 |
{ |
|
597 |
String partQuery=""; |
|
598 |
int lengthOfArray=principals.length; |
|
599 |
|
|
600 |
for (int i=0;i<(lengthOfArray-1);i++) |
|
601 |
{ |
|
602 |
partQuery=partQuery+"docid like '"+principals[i]+"',"; |
|
603 |
} |
|
604 |
|
|
605 |
//the last one dosen't has "'" |
|
606 |
partQuery=partQuery+"docid like '"+principals[(lengthOfArray-1)]+"'"; |
|
607 |
return partQuery; |
|
608 |
|
|
609 |
} |
|
610 |
|
|
611 |
/** |
|
612 |
* Check if a stirng array contains a given documents' owner |
|
613 |
* @param principals, a string array storing the username, groups name and |
|
614 |
* public. |
|
615 |
* @param docid, the id of given documents |
|
616 |
*/ |
|
617 |
private boolean containDocumentOwner( String [] principals, String docId) |
|
618 |
throws SQLException |
|
619 |
{ |
|
620 |
int lengthOfArray=principals.length; |
|
621 |
boolean hasRow; |
|
622 |
PreparedStatement pStmt=null; |
|
623 |
try |
|
624 |
{ |
|
625 |
pStmt = conn.prepareStatement( |
|
626 |
"SELECT 'x' FROM xml_documents " + |
|
627 |
"WHERE docid = ? AND user_owner = ?"); |
|
628 |
//check every element in the string array too see if it conatains |
|
629 |
//the owner of document |
|
630 |
for (int i=0; i<lengthOfArray; i++) |
|
631 |
{ |
|
632 |
|
|
633 |
// Bind the values to the query |
|
634 |
pStmt.setString(1, docId); |
|
635 |
pStmt.setString(2, principals[i]); |
|
636 |
|
|
637 |
pStmt.execute(); |
|
638 |
ResultSet rs = pStmt.getResultSet(); |
|
639 |
hasRow = rs.next(); |
|
640 |
if (hasRow) |
|
641 |
{ |
|
642 |
pStmt.close(); |
|
643 |
return true; |
|
644 |
}//if |
|
645 |
|
|
646 |
}//for |
|
647 |
}//try |
|
648 |
catch (SQLException e) |
|
649 |
{ |
|
650 |
pStmt.close(); |
|
651 |
|
|
652 |
throw new |
|
653 |
SQLException("AccessControlList.hasPermission(). " + |
|
654 |
"Error checking ownership for " + principals[0] + |
|
655 |
" on document #" + docId + ". " + e.getMessage()); |
|
656 |
}//catch |
|
657 |
|
|
658 |
|
|
659 |
pStmt.close(); |
|
660 |
|
|
661 |
return false; |
|
662 |
}//containDocumentOwner |
|
663 |
|
|
664 |
/** |
|
665 |
* Check if the permission order for user at that documents is allowFirst |
|
666 |
* @param principals, list of names of principals to check for |
|
667 |
* @param docid, document identifier to check for |
|
668 |
*/ |
|
669 |
private boolean isAllowFirst(String [] principals, String docId) |
|
670 |
throws SQLException, Exception |
|
671 |
{ |
|
672 |
int lengthOfArray=principals.length; |
|
673 |
boolean hasRow; |
|
674 |
|
|
675 |
//select permission order from database |
|
676 |
PreparedStatement pStmt = conn.prepareStatement( |
|
677 |
"SELECT perm_order FROM xml_access " + |
|
678 |
"WHERE principal_name= ? AND docid = ?"); |
|
679 |
|
|
680 |
//check every name in the array |
|
681 |
for (int i=0; i<lengthOfArray;i++) |
|
682 |
{ |
|
683 |
//bind value |
|
684 |
pStmt.setString(1, principals[i]);//user name |
|
685 |
pStmt.setString(2, docId);//docid |
|
686 |
|
|
687 |
pStmt.execute(); |
|
688 |
ResultSet rs = pStmt.getResultSet(); |
|
689 |
hasRow=rs.next(); |
|
690 |
if (hasRow) |
|
691 |
{ |
|
692 |
//get the permission order from data base |
|
693 |
String permissionOrder=rs.getString(1); |
|
694 |
//if the permission order is "allowFirst |
|
695 |
if (permissionOrder.compareTo(ALLOWFIRST)==0) |
|
696 |
{ |
|
697 |
pStmt.close(); |
|
698 |
return true; |
|
699 |
} |
|
700 |
else |
|
701 |
{ |
|
702 |
pStmt.close(); |
|
703 |
return false; |
|
704 |
} |
|
705 |
}//if |
|
706 |
}//for |
|
707 |
|
|
708 |
//if reach here, means there is no permssion record for given names and |
|
709 |
//docid. So throw a exception. |
|
710 |
pStmt.close(); |
|
711 |
throw new Exception("There is no permission record for user"+principals[0]+ |
|
712 |
"at document "+docId); |
|
713 |
|
|
714 |
}//isAllowFirst |
|
715 |
|
|
716 |
/** |
|
717 |
* Check if the users array has allow rules for given users, docid and |
|
718 |
* permission. |
|
719 |
* If it has permission rule and ticket count is greater than 0, the ticket |
|
720 |
* number will decrease one |
|
721 |
* @param principals, list of names of principals to check for |
|
722 |
* @param docid, document identifier to check for |
|
723 |
* @param permission, the permssion need to check |
|
724 |
*/ |
|
725 |
private boolean hasAllowRule(String [] principals, String docId, |
|
726 |
String permission) |
|
727 |
throws SQLException, Exception |
|
728 |
{ |
|
729 |
int lengthOfArray=principals.length; |
|
730 |
ResultSet rs; |
|
731 |
PreparedStatement pStmt; |
|
732 |
int permissionValue=intValue(permission); |
|
733 |
int permissionValueInTable; |
|
734 |
int ticketCount; |
|
735 |
|
|
736 |
//This sql statement will select entry with |
|
737 |
//begin_time<=currentTime<=end_time in xml_access table |
|
738 |
//If begin_time or end_time is null in table, isnull(begin_time, sysdate) |
|
739 |
//function will assign begin_time=sysdate |
|
740 |
pStmt = conn.prepareStatement( |
|
741 |
"SELECT permission, ticket_count " + |
|
742 |
"FROM xml_access " + |
|
743 |
"WHERE docid = ? " + |
|
744 |
"AND principal_name = ? " + |
|
745 |
"AND perm_type = ? " + |
|
746 |
"AND " + sysdate + |
|
747 |
" BETWEEN " + isnull + "(begin_time," + sysdate + ") " + |
|
748 |
"AND " + isnull + "(end_time," + sysdate + ")"); |
|
749 |
//bind docid, perm_type |
|
750 |
pStmt.setString(1, docId); |
|
751 |
pStmt.setString(3, ALLOW); |
|
752 |
|
|
753 |
//bind every elenment in user name array |
|
754 |
for (int i=0;i<lengthOfArray; i++) |
|
755 |
{ |
|
756 |
pStmt.setString(2, principals[i]); |
|
757 |
pStmt.execute(); |
|
758 |
rs=pStmt.getResultSet(); |
|
759 |
while (rs.next())//check every entry for one user |
|
760 |
{ |
|
761 |
permissionValueInTable=rs.getInt(1); |
|
762 |
ticketCount=rs.getInt(2); |
|
763 |
|
|
764 |
//permission is ok and ticketcount geat than 0 or ticket is null, |
|
765 |
//the user have a permission to access the file |
|
766 |
if ((( permissionValueInTable & permissionValue )== permissionValue ) |
|
767 |
&& (rs.wasNull()||ticketCount > 0)) |
|
768 |
{ |
|
769 |
//ticket count should minus one |
|
770 |
//ticketCount isnot null and greater than 0, order is allowfirst |
|
771 |
if (!rs.wasNull() && ticketCount>0 && isAllowFirst(principals,docId)) |
|
772 |
{ |
|
773 |
decreaseNumberOfAccess(permissionValueInTable, principals[i], |
|
774 |
docId, ALLOW, ALLOWFIRST); |
|
775 |
} |
|
776 |
//ticketCount isnot null and greater than 0, order is not allowfirst |
|
777 |
if (!rs.wasNull() &&ticketCount>0 && !isAllowFirst(principals,docId)) |
|
778 |
{ |
|
779 |
decreaseNumberOfAccess(permissionValueInTable, principals[i], |
|
780 |
docId, ALLOW, DENYFIRST); |
|
781 |
} |
|
782 |
pStmt.close(); |
|
783 |
return true; |
|
784 |
}//if |
|
785 |
}//while |
|
786 |
}//for |
|
787 |
pStmt.close(); |
|
788 |
return false;//no allow rule |
|
789 |
}//hasAllowRule |
|
790 |
|
|
791 |
/** |
|
792 |
* Check if the users array has explicit deny rules for given users, docid |
|
793 |
* and permission. That means the perm_type is deny and current time is |
|
794 |
* less than end_time and greater than begin time, or no time limit. |
|
795 |
* @param principals, list of names of principals to check for |
|
796 |
* @param docid, document identifier to check for |
|
797 |
* @param permission, the permssion need to check |
|
798 |
*/ |
|
799 |
private boolean hasExplicitDenyRule(String [] principals, String docId, |
|
800 |
String permission) |
|
801 |
throws SQLException |
|
802 |
{ |
|
803 |
int lengthOfArray=principals.length; |
|
804 |
ResultSet rs; |
|
805 |
PreparedStatement pStmt; |
|
806 |
int permissionValue=intValue(permission); |
|
807 |
int permissionValueInTable; |
|
808 |
|
|
809 |
|
|
810 |
//This sql statement will select entry with |
|
811 |
//begin_time<=currentTime<=end_time in xml_access table |
|
812 |
//If begin_time or end_time is null in table, isnull(begin_time, sysdate) |
|
813 |
//function will assign begin_time=sysdate |
|
814 |
pStmt = conn.prepareStatement( |
|
815 |
"SELECT permission " + |
|
816 |
"FROM xml_access " + |
|
817 |
"WHERE docid = ? " + |
|
818 |
"AND principal_name = ? " + |
|
819 |
"AND perm_type = ? " + |
|
820 |
"AND " + sysdate + |
|
821 |
" BETWEEN " + isnull + "(begin_time," + sysdate + ") " + |
|
822 |
"AND " + isnull + "(end_time," + sysdate + ")"); |
|
823 |
//bind docid, perm_type |
|
824 |
pStmt.setString(1, docId); |
|
825 |
pStmt.setString(3, DENY); |
|
826 |
|
|
827 |
//bind every elenment in user name array |
|
828 |
for (int i=0;i<lengthOfArray; i++) |
|
829 |
{ |
|
830 |
pStmt.setString(2, principals[i]); |
|
831 |
pStmt.execute(); |
|
832 |
rs=pStmt.getResultSet(); |
|
833 |
while (rs.next())//check every entry for one user |
|
834 |
{ |
|
835 |
permissionValueInTable=rs.getInt(1); |
|
836 |
|
|
837 |
//permission is ok the user doesn't have permission to access the file |
|
838 |
if (( permissionValueInTable & permissionValue )== permissionValue ) |
|
839 |
|
|
840 |
{ |
|
841 |
pStmt.close(); |
|
842 |
return true; |
|
843 |
}//if |
|
844 |
}//while |
|
845 |
}//for |
|
846 |
pStmt.close(); |
|
847 |
return false;//no deny rule |
|
848 |
}//hasExplicitDenyRule |
|
849 |
|
|
850 |
/** |
|
851 |
* Check if the users array has implicit deny rules for given users, docid |
|
852 |
* and permission. That means the though perm_type is "allow" but current |
|
853 |
* time is less than begin_time or greater than end time, or ticket count |
|
854 |
* is 0. |
|
855 |
* @param principals, list of names of principals to check for |
|
856 |
* @param docid, document identifier to check for |
|
857 |
* @param permission, the permssion need to check |
|
858 |
*/ |
|
859 |
private boolean hasImplicitDenyRule(String [] principals, String docId, |
|
860 |
String permission) |
|
861 |
throws SQLException |
|
862 |
{ |
|
863 |
int lengthOfArray=principals.length; |
|
864 |
ResultSet rs; |
|
865 |
PreparedStatement pStmt; |
|
866 |
int permissionValue=intValue(permission); |
|
867 |
int permissionValueInTable; |
|
868 |
|
|
869 |
|
|
870 |
//This sql statement will select entry with perm_type =allow and |
|
871 |
//currentTime is less than begin_time or greater than end time |
|
872 |
//in xml_access table. This is an implicit deny rule (allow is out of date) |
|
873 |
pStmt = conn.prepareStatement( |
|
874 |
"SELECT permission " + |
|
875 |
"FROM xml_access " + |
|
876 |
"WHERE docid = ? " + |
|
877 |
"AND principal_name = ? " + |
|
878 |
"AND perm_type = ? " + |
|
879 |
"AND " + sysdate + |
|
880 |
" < " + isnull + "(begin_time," + sysdate + ") " + |
|
881 |
"OR " + sysdate + " > "+ isnull + "(end_time," + sysdate + ")"); |
|
882 |
//bind docid, perm_type |
|
883 |
pStmt.setString(1, docId); |
|
884 |
pStmt.setString(3, ALLOW);//It is allow |
|
885 |
|
|
886 |
//bind every elenment in user name array |
|
887 |
for (int i=0;i<lengthOfArray; i++) |
|
888 |
{ |
|
889 |
pStmt.setString(2, principals[i]); |
|
890 |
pStmt.execute(); |
|
891 |
rs=pStmt.getResultSet(); |
|
892 |
while (rs.next())//check every entry for one user |
|
893 |
{ |
|
894 |
permissionValueInTable=rs.getInt(1); |
|
895 |
|
|
896 |
//permission is ok the user doesn't have permission to access the file |
|
897 |
if (( permissionValueInTable & permissionValue )== permissionValue ) |
|
898 |
|
|
899 |
{ |
|
900 |
pStmt.close(); |
|
901 |
//has a implicit deny rule: allow is out of date |
|
902 |
return true; |
|
903 |
}//if |
|
904 |
}//while |
|
905 |
}//for |
|
906 |
pStmt.close(); |
|
907 |
|
|
908 |
//Now, there is no implicit deny rule which is allow is out of date |
|
909 |
//another implicit deny rule need to be check: allow is out of ticketCount |
|
910 |
//ticketCount=0 |
|
911 |
pStmt = conn.prepareStatement( |
|
912 |
"SELECT permission " + |
|
913 |
"FROM xml_access " + |
|
914 |
"WHERE docid = ? " + |
|
915 |
"AND principal_name = ? " + |
|
916 |
"AND perm_type = ? " + |
|
917 |
"AND ticket_count = ?"); |
|
918 |
//bind docid, perm_type, ticket_count |
|
919 |
pStmt.setString(1, docId); |
|
920 |
pStmt.setString(3, ALLOW);//It is allow! |
|
921 |
pStmt.setInt(4,0); |
|
922 |
|
|
923 |
//bind every elenment in user name array |
|
924 |
for (int i=0;i<lengthOfArray; i++) |
|
925 |
{ |
|
926 |
pStmt.setString(2, principals[i]); |
|
927 |
pStmt.execute(); |
|
928 |
rs=pStmt.getResultSet(); |
|
929 |
while (rs.next())//check every entry for one user |
|
930 |
{ |
|
931 |
permissionValueInTable=rs.getInt(1); |
|
932 |
|
|
933 |
//permission is ok the user doesn't have permission to access the file |
|
934 |
if (( permissionValueInTable & permissionValue )== permissionValue ) |
|
935 |
|
|
936 |
{ |
|
937 |
|
|
938 |
pStmt.close(); |
|
939 |
//has a implicit deny rule: allow is out of ticketCount |
|
940 |
return true; |
|
941 |
}//if |
|
942 |
}//while |
|
943 |
}//for |
|
944 |
|
|
945 |
pStmt.close(); |
|
946 |
return false;//no implicit deny rule |
|
947 |
}//hasImplicitDenyRule |
|
948 |
|
|
949 |
/** |
|
950 |
* Creat a users pakages to check permssion rule, user itself, public and |
|
951 |
* the gourps the user belong will be include in this package |
|
952 |
* @param user, the name of user |
|
953 |
* @param groups, the string array of the groups that user belong to |
|
954 |
*/ |
|
955 |
private String [] createUsersPackage(String user, String [] groups) |
|
956 |
{ |
|
957 |
String [] usersPackage=null; |
|
958 |
int lengthOfPackage; |
|
959 |
|
|
960 |
if (groups!=null) |
|
961 |
{ |
|
962 |
//if gouprs is not null and user is not public, we should create a array |
|
963 |
//to store the groups and user and public. |
|
964 |
//So the length of userPackage is the length of group plus two |
|
965 |
if (user.compareTo(PUBLIC)!=0) |
|
966 |
{ |
|
967 |
lengthOfPackage=(groups.length)+2; |
|
968 |
usersPackage=new String [lengthOfPackage]; |
|
969 |
//the first two elements is user self and public |
|
970 |
usersPackage[0]=user; |
|
971 |
usersPackage[1]=PUBLIC; |
|
972 |
//put groups element from index 0 to lengthOfPackage-3 into userPackage |
|
973 |
//from index 2 to lengthOfPackage-1 |
|
974 |
for (int i=2; i<lengthOfPackage; i++) |
|
975 |
{ |
|
976 |
usersPackage[i]=groups[i-2]; |
|
977 |
} //for |
|
978 |
}//if user!=public |
|
979 |
else//use=public |
|
980 |
{ |
|
981 |
lengthOfPackage=(groups.length)+1; |
|
982 |
usersPackage=new String [lengthOfPackage]; |
|
983 |
//the first lements is public |
|
984 |
usersPackage[0]=PUBLIC; |
|
985 |
//put groups element from index 0 to lengthOfPackage-2 into userPackage |
|
986 |
//from index 1 to lengthOfPackage-1 |
|
987 |
for (int i=1; i<lengthOfPackage; i++) |
|
988 |
{ |
|
989 |
usersPackage[i]=groups[i-1]; |
|
990 |
} //for |
|
991 |
}//else user=public |
|
992 |
|
|
993 |
}//if groups!=null |
|
994 |
else |
|
995 |
{ |
|
996 |
//because no groups, the userPackage only need two elements |
|
997 |
//one is for user, the other is for public |
|
998 |
if (user.compareTo(PUBLIC)!=0) |
|
999 |
{ |
|
1000 |
lengthOfPackage=2; |
|
1001 |
usersPackage=new String [lengthOfPackage]; |
|
1002 |
usersPackage[0]=user; |
|
1003 |
usersPackage[1]=PUBLIC; |
|
1004 |
}//if user!=public |
|
1005 |
else //user==public |
|
1006 |
{ |
|
1007 |
//only put public into array |
|
1008 |
lengthOfPackage=1; |
|
1009 |
usersPackage=new String [lengthOfPackage]; |
|
1010 |
usersPackage[0]=PUBLIC; |
|
1011 |
} |
|
1012 |
}//else groups==null |
|
1013 |
return usersPackage; |
|
1014 |
}//createUsersPackage |
|
1015 |
|
|
1016 |
/** |
|
549 | 1017 |
* Check from db connection if at least one of the list of @principals |
550 | 1018 |
* has @permission on @docid. |
551 | 1019 |
* @param permission permission type to check for |
... | ... | |
553 | 1021 |
* @param docid document identifier to check on |
554 | 1022 |
*/ |
555 | 1023 |
public boolean hasPermission(String permission, String user, |
556 |
String[] groups, String docid )
|
|
1024 |
String[] groups, String docId )
|
|
557 | 1025 |
throws SQLException |
558 | 1026 |
{ |
1027 |
//detele the rev number if docid contains it |
|
1028 |
docId=MetaCatUtil.getDocIdFromString(docId); |
|
1029 |
boolean hasPermission=false; |
|
1030 |
String [] userPackage=null; |
|
1031 |
|
|
559 | 1032 |
// b' of the command line invocation |
560 | 1033 |
if ( (user == null) && (groups == null || groups.length == 0) ) { |
561 | 1034 |
return true; |
562 | 1035 |
} |
563 | 1036 |
|
564 |
// Check for @permission on @docid for @user and/or @groups |
|
565 |
boolean hasPermission = hasPermission(permission,user,docid); |
|
566 |
int i = 0; |
|
567 |
if ( groups != null ) { |
|
568 |
while ( !hasPermission && i<groups.length ) { |
|
569 |
hasPermission = hasPermission(permission,groups[i++],docid); |
|
570 |
} |
|
571 |
} |
|
572 |
// Check for @permission for "public" user |
|
573 |
if ( !hasPermission ) { |
|
574 |
hasPermission = hasPermission(permission,"public",docid); |
|
575 |
} |
|
576 | 1037 |
|
1038 |
//create a userpackage including user, public and group member |
|
1039 |
userPackage=createUsersPackage(user, groups); |
|
1040 |
|
|
1041 |
//if the requested document is access documents the user should |
|
1042 |
//have "all" permission not matter the requested permission |
|
1043 |
if (isAccessDocument(docId)) |
|
1044 |
{ |
|
1045 |
|
|
1046 |
// check for all permission on @docid for @userPackage |
|
1047 |
hasPermission = hasPermission(userPackage,docId,"all"); |
|
1048 |
|
|
1049 |
}//if |
|
1050 |
else //if it is not access documents, just check the request permission |
|
1051 |
{ |
|
1052 |
|
|
1053 |
// Check for @permission on @docid for @user and/or @groups |
|
1054 |
hasPermission = hasPermission(userPackage,docId, permission); |
|
1055 |
|
|
1056 |
}//else |
|
1057 |
|
|
577 | 1058 |
return hasPermission; |
578 | 1059 |
} |
579 |
|
|
1060 |
|
|
580 | 1061 |
/** |
581 |
* Check from db connection if @principal has @permission on @docid. |
|
582 |
* @param permission permission type to check for |
|
583 |
* @param principal name of principal to check for @permission |
|
584 |
* @param docid document identifier to check on |
|
1062 |
* Check from db connection if the users in String array @principals has |
|
1063 |
* @permission on @docid* |
|
1064 |
* @param principals, names in userPakcage need to check for @permission |
|
1065 |
* @param docid, document identifier to check on |
|
1066 |
* @param permission, permission (write or all...) to check for |
|
585 | 1067 |
*/ |
586 |
private boolean hasPermission(String permission,
|
|
587 |
String principal, String docid)
|
|
588 |
throws SQLException |
|
1068 |
private boolean hasPermission(String [] principals, String docId,
|
|
1069 |
String permission)
|
|
1070 |
throws SQLException
|
|
589 | 1071 |
{ |
590 |
//detele the rev number if docid contains it |
|
591 |
docid=MetaCatUtil.getDocIdFromString(docid); |
|
592 |
PreparedStatement pstmt; |
|
593 |
|
|
594 |
|
|
595 |
// since owner of resource has all permission on it, |
|
596 |
// check if @principal is owner of @docid in xml_documents table |
|
597 |
if ( principal != null ) { |
|
598 |
try { |
|
599 |
pstmt = conn.prepareStatement( |
|
600 |
"SELECT 'x' FROM xml_documents " + |
|
601 |
"WHERE docid = ? AND user_owner = ?"); |
|
602 |
// Bind the values to the query |
|
603 |
pstmt.setString(1, docid); |
|
604 |
pstmt.setString(2, principal); |
|
605 |
|
|
606 |
pstmt.execute(); |
|
607 |
ResultSet rs = pstmt.getResultSet(); |
|
608 |
boolean hasRow = rs.next(); |
|
609 |
pstmt.close(); |
|
610 |
if (hasRow) { |
|
1072 |
try |
|
1073 |
{ |
|
1074 |
//first, if there is a docid owner in user package, return true |
|
1075 |
//because doc owner has all permssion |
|
1076 |
if (containDocumentOwner(principals, docId)) |
|
1077 |
{ |
|
1078 |
|
|
611 | 1079 |
return true; |
612 |
} |
|
613 |
|
|
614 |
} catch (SQLException e) { |
|
615 |
throw new |
|
616 |
SQLException("AccessControlList.hasPermission(). " + |
|
617 |
"Error checking ownership for " + principal + |
|
618 |
" on document #" + docid + ". " + e.getMessage()); |
|
619 | 1080 |
} |
620 | 1081 |
|
621 |
//check to see if the file we are checking is an access file and if the |
|
622 |
//user that is trying to update it has ALL permissions |
|
1082 |
//If there is no owner in user package, checking the table |
|
1083 |
//check perm_order |
|
1084 |
if (isAllowFirst(principals, docId)) |
|
1085 |
{ |
|
1086 |
|
|
1087 |
if (hasExplicitDenyRule(principals, docId, permission)|| |
|
1088 |
hasImplicitDenyRule(principals, docId, permission)) |
|
1089 |
{ |
|
1090 |
//if it is allowfirst and has deny rule(either explicit or implicit) |
|
1091 |
//deny access |
|
1092 |
return false; |
|
1093 |
}//if |
|
1094 |
else if ( hasAllowRule(principals, docId, permission)) |
|
1095 |
{ |
|
1096 |
//if it is allowfirst and hasn't deny rule and has allow rule |
|
1097 |
//allow access |
|
1098 |
return true; |
|
1099 |
}//else if |
|
1100 |
else |
|
1101 |
{ |
|
1102 |
//other situation deny access |
|
1103 |
return false; |
|
1104 |
}//else |
|
1105 |
}//if isAllowFirst |
|
1106 |
else //denyFirst |
|
1107 |
{ |
|
1108 |
if (hasAllowRule(principals, docId, permission)) |
|
1109 |
{ |
|
1110 |
//if it is denyFirst and has allow rule, allow access |
|
1111 |
return true; |
|
1112 |
} |
|
1113 |
else |
|
1114 |
{ |
|
1115 |
//if it is denyfirst but no allow rule, deny access |
|
1116 |
return false; |
|
1117 |
} |
|
1118 |
}//else denyfirst |
|
1119 |
}//try |
|
1120 |
catch (Exception e) |
|
1121 |
{ |
|
1122 |
MetaCatUtil.debugMessage("There is a exception in hasPermission method: " |
|
1123 |
+e.getMessage()); |
|
1124 |
} |
|
1125 |
return false; |
|
1126 |
}//hasPermission |
|
1127 |
|
|
1128 |
private boolean hasValidDenyEntry(String persmission, String principal, |
|
1129 |
String docId) |
|
1130 |
throws SQLException |
|
1131 |
{ |
|
1132 |
//detele the rev number if docid contains it |
|
1133 |
docId=MetaCatUtil.getDocIdFromString(docId); |
|
1134 |
PreparedStatement pStmt; |
|
1135 |
String permissionType; |
|
1136 |
int accessValue; |
|
1137 |
|
|
1138 |
|
|
623 | 1139 |
try |
624 | 1140 |
{ |
625 |
pstmt = conn.prepareStatement("select 'x' from xml_access where " + |
|
626 |
"accessfileid like '" + docid + |
|
627 |
"' and principal_name like '" + principal+ |
|
628 |
"' and perm_type like 'allow' and " + |
|
629 |
"permission = 7"); |
|
630 |
pstmt.execute(); |
|
631 |
ResultSet rs = pstmt.getResultSet(); |
|
1141 |
pStmt = conn.prepareStatement("select perm_type, permission, begin_time" |
|
1142 |
+ ", end_time from xml_access where " + |
|
1143 |
"docid like '" + docId + "' and " |
|
1144 |
+ "principal_name like '"+principal+"'"); |
|
1145 |
pStmt.execute(); |
|
1146 |
ResultSet rs = pStmt.getResultSet(); |
|
632 | 1147 |
boolean hasRow = rs.next(); |
633 |
pstmt.close();
|
|
1148 |
pStmt.close();
|
|
634 | 1149 |
if(hasRow) |
635 | 1150 |
{ |
636 | 1151 |
return true; |
... | ... | |
640 | 1155 |
{ |
641 | 1156 |
throw new SQLException("AccessControlList.hasPermission():2 " + |
642 | 1157 |
"Error checking ownership for " + principal + |
643 |
" on document #" + docid + ". " + e.getMessage());
|
|
1158 |
" on document #" + docId + ". " + e.getMessage());
|
|
644 | 1159 |
} |
645 |
|
|
646 |
// check @principal's @permission on @docid from xml_access table |
|
647 |
int accessValue = 0; |
|
648 |
int ticketCount = 0; |
|
649 |
String permOrder = ""; |
|
650 |
try { |
|
651 |
pstmt = conn.prepareStatement( |
|
652 |
"SELECT permission, perm_order, ticket_count " + |
|
653 |
"FROM xml_access " + |
|
654 |
"WHERE docid = ? " + |
|
655 |
"AND principal_name = ? " + |
|
656 |
"AND perm_type = ? " + |
|
657 |
"AND " + sysdate + |
|
658 |
" BETWEEN " + isnull + "(begin_time," + sysdate + ") " + |
|
659 |
"AND " + isnull + "(end_time," + sysdate + ")"); |
|
660 |
// check if it is "deny" with "allowFirst" first |
|
661 |
// Bind the values to the query |
|
662 |
pstmt.setString(1, docid); |
|
663 |
pstmt.setString(2, principal); |
|
664 |
pstmt.setString(3, "deny"); |
|
665 |
|
|
666 |
pstmt.execute(); |
|
667 |
ResultSet rs = pstmt.getResultSet(); |
|
668 |
boolean hasRows = rs.next(); |
|
669 |
while ( hasRows ) { |
|
670 |
accessValue = rs.getInt(1); |
|
671 |
permOrder = rs.getString(2); |
|
672 |
ticketCount = rs.getInt(3); |
|
673 |
if ( ( accessValue & intValue(permission) ) == intValue(permission) && |
|
674 |
( permOrder.equals("allowFirst") ) && |
|
675 |
( rs.wasNull() || ticketCount > 0 ) ) { |
|
676 |
if ( !rs.wasNull() && ticketCount > 0 ) { |
|
677 |
decreaseNumberOfAccess(accessValue,principal,docid, |
|
678 |
"deny","allowFirst"); |
|
679 |
} |
|
680 |
pstmt.close(); |
|
681 |
return false; |
|
682 |
} |
|
683 |
hasRows = rs.next(); |
|
684 |
} |
|
685 |
|
|
686 |
|
|
687 |
// it is not denied then check if it is "allow" |
|
688 |
// Bind the values to the query |
|
689 |
pstmt.setString(1, docid); |
|
690 |
pstmt.setString(2, principal); |
|
691 |
pstmt.setString(3, "allow"); |
|
692 |
|
|
693 |
pstmt.execute(); |
|
694 |
rs = pstmt.getResultSet(); |
|
695 |
hasRows = rs.next(); |
|
696 |
while ( hasRows ) { |
|
697 |
accessValue = rs.getInt(1); |
|
698 |
permOrder = rs.getString(2); |
|
699 |
ticketCount = rs.getInt(3); |
|
700 |
if ( ( accessValue & intValue(permission) )==intValue(permission) && |
|
701 |
( rs.wasNull() || ticketCount > 0 ) ) { |
|
702 |
if ( !rs.wasNull() && ticketCount > 0 ) { |
|
703 |
decreaseNumberOfAccess(accessValue,principal, |
|
704 |
docid,"allow",permOrder); |
|
705 |
} |
|
706 |
pstmt.close(); |
|
707 |
return true; |
|
708 |
} |
|
709 |
hasRows = rs.next(); |
|
710 |
} |
|
711 |
|
|
712 |
|
|
713 |
// it is not allowed then check if it is "deny" with "denyFirst" |
|
714 |
// Bind the values to the query |
|
715 |
pstmt.setString(1, docid); |
|
716 |
pstmt.setString(2, principal); |
|
717 |
pstmt.setString(3, "deny"); |
|
718 |
|
|
719 |
pstmt.execute(); |
|
720 |
rs = pstmt.getResultSet(); |
|
721 |
hasRows = rs.next(); |
|
722 |
while ( hasRows ) { |
|
723 |
accessValue = rs.getInt(1); |
|
724 |
permOrder = rs.getString(2); |
|
725 |
ticketCount = rs.getInt(3); |
|
726 |
if ( ( accessValue & intValue(permission) ) == intValue(permission) && |
|
727 |
( permOrder.equals("denyFirst") ) && |
|
728 |
( rs.wasNull() || ticketCount > 0 ) ) { |
|
729 |
if ( !rs.wasNull() && ticketCount > 0 ) { |
|
730 |
decreaseNumberOfAccess(accessValue,principal,docid, |
|
731 |
"deny","denyFirst"); |
|
732 |
} |
|
733 |
pstmt.close(); |
|
734 |
return false; |
|
735 |
} |
|
736 |
hasRows = rs.next(); |
|
737 |
} |
|
738 |
|
|
739 |
|
|
740 |
pstmt.close(); |
|
741 |
return false; |
|
742 |
|
|
743 |
} catch (SQLException e) { |
|
744 |
throw new |
|
745 |
SQLException("AccessControlList.hasPermission(). " + |
|
746 |
"Error checking " + permission + " permission for " + |
|
747 |
principal + " on document #" + docid + ". " + |
|
748 |
e.getMessage()); |
|
749 |
} |
|
750 |
} |
|
751 |
|
|
752 |
return false; |
|
1160 |
return false; |
|
753 | 1161 |
} |
754 |
|
|
755 | 1162 |
/* Decrease the number of access to @docid for @principal in db. */ |
756 | 1163 |
private void decreaseNumberOfAccess(int permission, String principal, |
757 | 1164 |
String docid, String permType, |
... | ... | |
790 | 1197 |
* @param groups names of user's groups to which user belongs |
791 | 1198 |
*/ |
792 | 1199 |
public String getACL(String docid, String user, String[] groups) |
793 |
throws SQLException
|
|
1200 |
throws SQLException |
|
794 | 1201 |
{ |
795 | 1202 |
StringBuffer output = new StringBuffer(); |
796 | 1203 |
StringBuffer outTemp = new StringBuffer(); |
Also available in: Unified diff
The two hasPermission methods were rewritten. Some logic bugs were fixed. Now user, public and group will not be checked speratedly, but they will be check together as string array. In order to do this, private methods isAccessDocument, containDocumentOwner, isAllowFirst, hasAllowRule, hasExplicitDenyRule, hasImplicitDenyRule, and createUsersPackage were added.