Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
names.py422 linesDownload Raw Back to gssapi
1 2import typing as t3 4from gssapi.raw import names as rname5from gssapi.raw import NameType6from gssapi.raw import named_tuples as tuples7from gssapi.raw import oids as roids8from gssapi import _utils9 10from collections.abc import MutableMapping, Iterable11 12rname_rfc6680 = _utils.import_gssapi_extension('rfc6680')13rname_rfc6680_comp_oid = _utils.import_gssapi_extension('rfc6680_comp_oid')14 15 16class Name(rname.Name):17    """A GSSAPI Name18 19    This class represents a GSSAPI name which may be used with and/or returned20    by other GSSAPI methods.21 22    It inherits from the low-level GSSAPI :class:`~gssapi.raw.names.Name`23    class, and thus may used with both low-level and high-level API methods.24 25    This class may be pickled and unpickled, as well as copied.26 27    The :class:`str` and :class:`bytes` methods may be used to retrieve the28    text of the name.29 30    Note:31        Name strings will be automatically converted to and from unicode32        strings as appropriate.  If a method is listed as returning a33        :class:`str` object, it will return a unicode string.34 35        The encoding used will be python-gssapi's current encoding, which36        defaults to UTF-8.37    """38 39    __slots__ = ('_attr_obj')40 41    def __new__(42        cls,43        base: t.Optional[t.Union[rname.Name, bytes, str]] = None,44        name_type: t.Optional[roids.OID] = None,45        token: t.Optional[bytes] = None,46        composite: bool = False,47    ) -> "Name":48        if token is not None:49            if composite:50                if rname_rfc6680 is None:51                    raise NotImplementedError(52                        "Your GSSAPI implementation does not support RFC 6680 "53                        "(the GSSAPI naming extensions)")54 55                if rname_rfc6680_comp_oid is not None:56                    base_name = rname.import_name(token,57                                                  NameType.composite_export)58                    displ_name = rname.display_name(base_name, name_type=True)59                    if displ_name.name_type == NameType.composite_export:60                        # NB(directxman12): there's a bug in MIT krb5 <= 1.1361                        # where GSS_C_NT_COMPOSITE_EXPORT doesn't trigger62                        # immediate import logic.  However, we can just use63                        # the normal GSS_C_NT_EXPORT_NAME in this case.64                        base_name = rname.import_name(token, NameType.export)65                else:66                    # NB(directxman12): some older versions of MIT krb5 don't67                    # have support for the GSS_C_NT_COMPOSITE_EXPORT, but do68                    # support composite tokens via GSS_C_NT_EXPORT_NAME.69                    base_name = rname.import_name(token, NameType.export)70            else:71                base_name = rname.import_name(token, NameType.export)72        elif isinstance(base, rname.Name):73            base_name = base74        else:75            if isinstance(base, str):76                base = base.encode(_utils._get_encoding())77 78            base_name = rname.import_name(79                base,  # type: ignore[arg-type]80                name_type)81 82        return t.cast("Name", super(Name, cls).__new__(cls, base_name))83 84    def __init__(85        self,86        base: t.Optional[t.Union[rname.Name, bytes, str]] = None,87        name_type: t.Optional[roids.OID] = None,88        token: t.Optional[bytes] = None,89        composite: bool = False,90    ) -> None:91        """92        The constructor can be used to "import" a name from a human readable93        representation, or from a token, and can also be used to convert a94        low-level :class:`gssapi.raw.names.Name` object into a high-level95        object.96 97        If a :class:`~gssapi.raw.names.Name` object from the low-level API98        is passed as the `base` argument, it will be converted into a99        high-level object.100 101        If the `token` argument is used, the name will be imported using102        the token.  If the token was exported as a composite token,103        pass `composite=True`.104 105        Otherwise, a new name will be created, using the `base` argument as106        the human-readable string and the `name_type` argument to denote the107        name type.108 109        Raises:110            ~gssapi.exceptions.BadNameTypeError111            ~gssapi.exceptions.BadNameError112            ~gssapi.exceptions.BadMechanismError113        """114 115        self._attr_obj: t.Optional[_NameAttributeMapping]116 117        if rname_rfc6680 is not None:118            self._attr_obj = _NameAttributeMapping(self)119        else:120            self._attr_obj = None121 122    def __str__(self) -> str:123        return bytes(self).decode(_utils._get_encoding())124 125    def __unicode__(self) -> str:126        # Python 2 -- someone asked for unicode127        return self.__bytes__().decode(_utils._get_encoding())128 129    def __bytes__(self) -> bytes:130        # Python 3 -- someone asked for bytes131        return rname.display_name(self, name_type=False).name132 133    def display_as(134        self,135        name_type: roids.OID,136    ) -> str:137        """138        Display this name as the given name type.139 140        This method attempts to display the current :class:`Name`141        using the syntax of the given :class:`~gssapi.raw.types.NameType`, if142        possible.143 144        Warning:145 146            In MIT krb5 versions below 1.13.3, this method can segfault if147            the name was not *originally* created with a `name_type` that was148            not ``None`` (even in cases when a ``name_type``149            is later "added", such as via :meth:`canonicalize`).150            **Do not use this method unless you are sure the above151            conditions can never happen in your code.**152 153        Warning:154 155            In addition to the above warning, current versions of MIT krb5 do156            not actually fully implement this method, and it may return157            incorrect results in the case of canonicalized names.158 159        :requires-ext:`rfc6680`160 161        Args:162            name_type (~gssapi.OID): the :class:`~gssapi.raw.types.NameType` to163                use to display the given name164 165        Returns:166            str: the displayed name167 168        Raises:169            ~gssapi.exceptions.OperationUnavailableError170        """171 172        if rname_rfc6680 is None:173            raise NotImplementedError("Your GSSAPI implementation does not "174                                      "support RFC 6680 (the GSSAPI naming "175                                      "extensions)")176        return rname_rfc6680.display_name_ext(self, name_type).decode(177            _utils._get_encoding())178 179    @property180    def name_type(self) -> t.Optional[roids.OID]:181        """The :class:`~gssapi.raw.types.NameType` of this name"""182        return rname.display_name(self, name_type=True).name_type183 184    def __eq__(185        self,186        other: object,187    ) -> bool:188        if not isinstance(other, rname.Name):189            # maybe something else can compare this190            # to other classes, but we certainly can't191            return NotImplemented192        else:193            return rname.compare_name(self, other)194 195    def __ne__(196        self,197        other: object,198    ) -> bool:199        return not self.__eq__(other)200 201    def __repr__(self) -> str:202        disp_res = rname.display_name(self, name_type=True)203        return "Name({name!r}, {name_type})".format(204            name=disp_res.name, name_type=disp_res.name_type)205 206    def export(207        self,208        composite: bool = False,209    ) -> bytes:210        """Export this name as a token.211 212        This method exports the name into a byte string which can then be213        imported by using the `token` argument of the constructor.214 215        Args:216            composite (bool): whether or not use to a composite token --217                :requires-ext:`rfc6680`218 219        Returns:220            bytes: the exported name in token form221 222        Raises:223            ~gssapi.exceptions.MechanismNameRequiredError224            ~gssapi.exceptions.BadNameTypeError225            ~gssapi.exceptions.BadNameError226        """227 228        if composite:229            if rname_rfc6680 is None:230                raise NotImplementedError("Your GSSAPI implementation does "231                                          "not support RFC 6680 (the GSSAPI "232                                          "naming extensions)")233 234            return rname_rfc6680.export_name_composite(self)235        else:236            return rname.export_name(self)237 238    def canonicalize(239        self,240        mech: roids.OID241    ) -> "Name":242        """Canonicalize a name with respect to a mechanism.243 244        This method returns a new :class:`Name` that is canonicalized according245        to the given mechanism.246 247        Args:248            mech (~gssapi.OID): the :class:`MechType` to use249 250        Returns:251            Name: the canonicalized name252 253        Raises:254            ~gssapi.exceptions.BadMechanismError255            ~gssapi.exceptions.BadNameTypeError256            ~gssapi.exceptions.BadNameError257        """258 259        return type(self)(rname.canonicalize_name(self, mech))260 261    def __copy__(self) -> "Name":262        return type(self)(rname.duplicate_name(self))263 264    def __deepcopy__(265        self,266        memo: t.Dict,267    ) -> "Name":268        return type(self)(rname.duplicate_name(self))269 270    def _inquire(271        self,272        **kwargs: t.Any,273    ) -> tuples.InquireNameResult:274        """Inspect this name for information.275 276        This method inspects the name for information.277 278        If no keyword arguments are passed, all available information279        is returned.  Otherwise, only the keyword arguments that280        are passed and set to `True` are returned.281 282        Args:283            mech_name (bool): get whether this is a mechanism name,284                and, if so, the associated mechanism285            attrs (bool): get the attributes names for this name286 287        Returns:288            InquireNameResult: the results of the inquiry, with unused289                fields set to None290 291        Raises:292            ~gssapi.exceptions.GSSError293        """294 295        if rname_rfc6680 is None:296            raise NotImplementedError("Your GSSAPI implementation does not "297                                      "support RFC 6680 (the GSSAPI naming "298                                      "extensions)")299 300        if not kwargs:301            default_val = True302        else:303            default_val = False304 305        attrs = kwargs.get('attrs', default_val)306        mech_name = kwargs.get('mech_name', default_val)307 308        return rname_rfc6680.inquire_name(self, mech_name=mech_name,309                                          attrs=attrs)310 311    @property312    def is_mech_name(self) -> bool:313        """Whether or not this name is a mechanism name314        (:requires-ext:`rfc6680`)315        """316        return self._inquire(mech_name=True).is_mech_name317 318    @property319    def mech(self) -> roids.OID:320        """The mechanism associated with this name (:requires-ext:`rfc6680`)321        """322        return self._inquire(mech_name=True).mech323 324    @property325    def attributes(self) -> t.Optional[MutableMapping]:326        """The attributes of this name (:requires-ext:`rfc6680`)327 328        The attributes are presenting in the form of a329        :class:`~collections.abc.MutableMapping` (a dict-like object).330 331        Retrieved values will always be in the form of :class:`frozenset`.332 333        When assigning values, if iterables are used, they be considered to be334        the set of values for the given attribute.  If a non-iterable is used,335        it will be considered a single value, and automatically wrapped in an336        iterable.337 338        Note:339            String types (includes :class:`bytes`) are not considered to340            be iterables in this case.341        """342        if self._attr_obj is None:343            raise NotImplementedError("Your GSSAPI implementation does not "344                                      "support RFC 6680 (the GSSAPI naming "345                                      "extensions)")346 347        return self._attr_obj348 349 350class _NameAttributeMapping(MutableMapping):351 352    """Provides dict-like access to RFC 6680 Name attributes."""353    def __init__(354        self,355        name: Name,356    ) -> None:357        self._name = name358 359    def __getitem__(360        self,361        key: t.Union[bytes, str],362    ) -> tuples.GetNameAttributeResult:363        if isinstance(key, str):364            key = key.encode(_utils._get_encoding())365 366        res = rname_rfc6680.get_name_attribute(  # type: ignore[union-attr]367            self._name, key)368        res = t.cast(tuples.GetNameAttributeResult, res)369 370        return tuples.GetNameAttributeResult(list(res.values),371                                             list(res.display_values),372                                             res.authenticated,373                                             res.complete)374 375    def __setitem__(376        self,377        key: t.Union[bytes, str],378        value: t.Union[379            tuples.GetNameAttributeResult, t.Tuple[bytes, bool], bytes380        ],381    ) -> None:382        if isinstance(key, str):383            key = key.encode(_utils._get_encoding())384 385        rname_rfc6680.delete_name_attribute(  # type: ignore[union-attr]386            self._name, key)387 388        attr_value: t.List[bytes]389        if isinstance(value, tuples.GetNameAttributeResult):390            complete = value.complete391            attr_value = value.values392        elif isinstance(value, tuple) and len(value) == 2:393            complete = t.cast(bool, value[1])394            attr_value = [t.cast(bytes, value[0])]395        else:396            complete = False397 398        if (isinstance(value, (str, bytes)) or399                not isinstance(value, Iterable)):400            # NB(directxman12): this allows us to easily assign a single401            # value, since that's a common case402            attr_value = [value]403 404        rname_rfc6680.set_name_attribute(  # type: ignore[union-attr]405            self._name, key, attr_value, complete=complete)406 407    def __delitem__(408        self,409        key: t.Union[bytes, str],410    ) -> None:411        if isinstance(key, str):412            key = key.encode(_utils._get_encoding())413 414        rname_rfc6680.delete_name_attribute(  # type: ignore[union-attr]415            self._name, key)416 417    def __iter__(self) -> t.Iterator[bytes]:418        return iter(self._name._inquire(attrs=True).attrs)419 420    def __len__(self) -> int:421        return len(self._name._inquire(attrs=True).attrs)422 
codekingpro/portable-devtools · Team Ai