Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Wiki Markup
h1. Purpose:

...



This how-to is for the users who want to setup an environment with CAS in front and OpenLDAP, GSSAPI, Kerberos as the authorization engine.

...



h1. Environment:

...

 

Server: Fedora Core 6 + CAS 3.1 + Tomcat 5.5.20 + OpenLDAP 2.3.30 + Cyrus SASL 2.1.22 + Kerboeros 1.5-23

...



Client: Fedora Core 6 + Firefox

...

      Windows XP + IE6 SP2

Config DNS:

To make SSL and Kerberos work, I have to config DNS at the very beginning.

...

 2

      Windows XP + IE6 SP2

h1. Config DNS:

To make SSL and Kerberos work, I have to config DNS at the very beginning.

h4. 1. Edit /etc/named.conf, add langhua zone:

...



{code
:title
=/etc/named.conf
|borderStyle
=solid
}
zone "1.168.192.IN-ADDR.ARPA." IN {
        type master;
        file "192.168.1.db";
};

zone "langhua." IN {
        type master;
        file "named.langhua";
};
{code}

h4. 2. Create /var/named/named.langhua

...



{code
:title
=/var/named/named.langhua
|borderStyle
=solid
}
$TTL 1H
@	SOA	localhost.	root.localhost. (	2
						3H
						1H
						1W
						1H )
	NS	localhost.

auth.langhua.                          IN 1H A 192.168.1.110

_kerberos                              IN TXT "AUTH.LANGHUA"
_kerberos._udp.auth.langhua.           IN SRV 0 0 88  auth.langhua.
_kerberos-master._udp.auth.langhua.    IN SRV 0 0 88  auth.langhua.
_kerberos-adm._tcp.auth.langhua.       IN SRV 0 0 749 auth.langhua.
_kpasswd._udp.auth.langhua.            IN SRV 0 0 464 auth.langhua.

_ldap._tcp.auth.langhua.               IN SRV 0 0 389 auth.langhua.
_ldap._tcp.dc._msdcs.auth.langhua.     IN SRV 0 0 389 auth.langhua.
_kerberos._tcp.dc._msdcs.auth.langhua. IN SRV 0 0 88  auth.langhua.
{code}

h4. 3. Create /var/name/192.168.1.db

...



{code
:title
=/var/name/192.168.1.db
|borderStyle
=solid
}
$TTL 1H
@	SOA	localhost.	root.localhost. (	2
						3H
						1H
						1W
						1H )
	NS	localhost.
110	PTR	auth.langhua.
{code}

h4. 4. nslookup auth.langhua

...



Server:         192.168.1.110

...


Address:        192.168.1.110#53

...



Name:   auth.langhua

...


Address: 192.168.1.110

...



h4. 5. dig \-x 192.168.1.110

...



; <<>> DiG 9.3.4-P1 <<>> \-x 192.168.1.110

...


;; global options:  printcmd

...


;; Got answer:

...


;; \->>HEADER<<\- opcode: QUERY, status: NOERROR, id: 3829

...


;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2

...



;; QUESTION SECTION:

...


;110.1.168.192.in-addr.arpa.    IN

...

      PTR

;; ANSWER SECTION:

...


110.1.168.192.in-addr.arpa. 3600 IN     PTR     auth.langhua.

...



;; AUTHORITY SECTION:

...


1.168.192.in-addr.arpa. 3600    IN      NS      localhost.

...



;; ADDITIONAL SECTION:

...


localhost.              86400   IN      A       127.0.0.1

...


localhost.              86400   IN      AAAA    ::1

...



;; Query time: 1 msec

...


;; SERVER: 192.168.1.110#53(192.168.1.110)

...


;; WHEN: Thu Nov 29 04:53:02 2007

...


;; MSG SIZE  rcvd: 137

...



h1. Config Kerberos:

...




h4. 1. Config /etc/krb5.conf

...



{code
:title
=/etc/krb5.conf
|borderStyle
=solid
}
[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 default_realm = AUTH.LANGHUA
 dns_lookup_realm = false
 dns_lookup_kdc = false
 ticket_lifetime = 24h
 forwardable = true

[realms]
 AUTH.LANGHUA = {
  kdc = auth.langhua:88
  admin_server = auth.langhua:749
  default_domain = langhua
 }

[domain_realm]
.langhua = AUTH.LANGHUA

[kdc]
 profile = /var/kerberos/krb5kdc/kdc.conf

[appdefaults]
 pam = {
   debug = false
   ticket_lifetime = 36000
   renew_lifetime = 36000
   forwardable = true
   krb4_convert = false
 }
{code}

h4. 2. kdb5_util create \-s

...




h4. 3. Add users to Kerberos

...



kadmin.local \-q "addprinc krbadm@AUTH.LANGHUA"

...


kadmin.local \-q "addprinc ldapadm@AUTH.LANGHUA"

...


kadmin.local \-q "addprinc host/auth.langhua@AUTH.LANGHUA"

...


kadmin.local \-q "addprinc ldap/auth.langhua@AUTH.LANGHUA"

...



If you face this error in this step, delete the files under /var/kerberos/krb5kdc/ and redo the above step 2 and 3:

...


kadmin.local: Cannot find/read stored master key while initializing kadmin.local interface

...



h4. 4. Edit /var/kerberos/krb5kdc/kdc.conf

...



This file is configed in /etc/krb5.conf.

...


{code
:title
=/var/kerberos/krb5kdc/kdc.conf
|borderStyle
=solid
}
[kdcdefaults]
 acl_file = /var/kerberos/krb5kdc/kadm5.acl
 dict_file = /usr/share/dict/words
 admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
 v4_mode = nopreauth

[realms]
  AUTH.LANGHUA = {
  master_key_type = des3-hmac-sha1
  supported_enctypes = des3-hmac-sha1:normal des-cbc-crc:normal
 }
{code}

h4. 5. Edit /var/kerberos/krb5kdc/kadm5.acl

...



This file is configed in /var/kerberos/krb5kdc/kdc.conf.

...


{code
:title
=/var/kerberos/krb5kdc/kadm5.acl
|borderStyle
=solid
}
kadmin/admin@AUTH.LANGHUA              *
ldap/auth.langhua@AUTH.LANGHUA         *
krbadm@AUTH.LANGHUA                    *
*/*@AUTH.LANGHUA                       i
host/auth.langhua@AUTH.LANGHUA         *
{code}

h4. 6. Config /var/kerberos/krb5kdc/kadm5.keytab

...



This file is configed in /var/kerberos/krb5kdc/kdc.conf.

...


kadmin.local \-q "ktadd \-k /var/kerberos/krb5kdc/kadm5.keytab kadmin/admin"

...


kadmin.local \-q "ktadd \-k /var/kerberos/krb5kdc/kadm5.keytab kadmin/changepw"

...



h4. 7. Edit /etc/krb.realms

...



{code
:title
=/etc/krb.realms
|borderStyle
=solid
}
auth.langhua            AUTH.LANGHUA
.langhua                AUTH.LANGHUA

{code}

h4. 8. Edit /etc/krb.conf

...



{code
:title
=/etc/krb.conf
|borderStyle
=solid
}
AUTH.LANGHUA
AUTH.LANGHUA	auth.langhua:88
AUTH.LANGHUA	auth.langhua:749 admin server
{code}

h4. 9. Start Kerberos

...



/etc/init.d/kadmin start

...


/etc/init.d/krb5kdc start

...



h1. Test

...

 Kerberos


h4. 1. kadmin.local \-q "ktadd \-k /etc/krb5.keytab host/auth.langhua"

...




h4. 2. kinit \-k host/auth.langhua

...



If the error "kinit(v5): Password incorrect while getting initial credentials" found, delete /etc/krb5.keytab, and redo step 1 and 2.

...



h4. 3. klist

...



Ticket cache: FILE:/tmp/krb5cc_0

...


Default principal: host/auth.langhua@AUTH.LANGHUA

...



Valid starting

...

     Expires            Service principal
11/29/07 02:44:44  11/30/07 02:44:44  krbtgt/AUTH.LANGHUA@AUTH.LANGHUA

...



Kerberos 4 ticket cache: /tmp/tkt0

...


klist: You have no tickets cached

...



h4. 4. Make sure kvno numbers are the same

...



4.1 kvno host/auth.langhua

...



host/auth.langhua@AUTH.LANGHUA: kvno = 5

...



4.2 klist \-k /etc/krb5.keytab

...



Keytab name: FILE:/etc/krb5.keytab

...


KVNO Principal

...


\-\--\- --\-----------------------------------------------------------------------\-

...


5 host/auth.langhua@AUTH.LANGHUA

...


5 host/auth.langhua@AUTH.LANGHUA

...



If the numbers are not same, redo step 1, 2, 3.

...



h4. 5. Test ktelnetd, krlogind, krshd

...



5.1 Edit \~/.k5login

...



host/auth.langhua@AUTH.LANGHUA

...



5.2 Start xinetd

...



chkconfig klogin on

...


chkconfig kshell on

...


chkconfig eklogin on

...


chkconfig krb5-telnet on

...


/etc/init.d/xinetd restart

...



5.3 krlogin auth.langhua \-k AUTH.LANGHUA

...



This rlogin session is encrypting all data transmissions.

...


Last login: Thu Nov 29 04:46:08 from auth.langhua

...


You have new mail.

...



5.4 telnet \-x 192.168.1.110 \-k AUTH.LANGHUA

...



Trying 192.168.1.110...

...


Connected to auth.langhua (192.168.1.110).

...


Escape character is '^\]'.

...


Waiting for encryption to be negotiated...

...


\[ Kerberos V5 accepts you as ``host/auth.langhua@AUTH.LANGHUA'' \]

...


done.

...


Last login: Thu Nov 29 04:46:23 from auth.langhua

...


You have new mail.

...



5.5 rsh 192.168.1.110 \-k AUTH.LANGHUA

...



Last login: Thu Nov 29 04:47:00 from auth.langhua

...


You have new mail.

...



*Kerberos configuration is OK now.*

h1.

...

 Config Cyrus SASL GSSAPI


h4. 1. Add ldap service
\\

1.1 kadmin.local \-q "addprinc \-randkey ldap/auth.langhua@AUTH.LANGHUA"

1.2 check /var/kerberos/krb5kdc/kadm5.acl has ldap service configed

1.3 kadmin.local \-q "ktadd \-k /etc/krb5.keytab ldap/auth.langhua"

h4. 2. Add a test user

2.1 kadmin.local \-q "addprinc test@AUTH.LANGHUA"

2.2 kadmin.local \-q "ktadd \-k /etc/krb5.keytab test"

2.3 Edit \~/.k5login

test@AUTH.LANGHUA

h4. 3. Verify GSSAPI works on your system

3.1 sasl2-sample-server \-s ldap \-m GSSAPI

trying 10, 1, 6
trying 2, 1, 6
bind: Address already in use

3.2 sasl2-sample-client \-s ldap \-m GSSAPI auth.langhua

receiving capability list... recv: {6}
GSSAPI
GSSAPI
please enter an authorization id:&nbsp; test

send: {6}
GSSAPI
send: {1}
Y
send: {525}
`\[82\]\[2\]\[9\]\[6\]\[9\]*\[86\]H\[86\]\[F7\]\[12\]\[1\]\[2\]\[2\]\[1\]\[0\]n\[82\]\[1\]\[F8\]0\[82\]\[1\]\[F4\]\[A0\]\[3\]\[2\]\[1\]\[5\]\[A1\]\[3\]\[2\]\[1\]\[E\]\[A2\]\[7\]\[3\]\[5\]\[0\] \[0\]\[0\]\[0\]\[A3\]\[82\]\[1\]\[10\]a\[82\]\[1\]\[C\]0\[82\]\[1\]\[8\]\[A0\]\[3\]\[2\]\[1\]\[5\]\[A1\]\[E\]\[1B\]\[C\]AUTH.LANGHUA\[A2\]\[1F\]0\[1D\]\[A0\]\[3\]\[2\]\[1\]\[3\]\[A1\]\[16\]0\[14\]\[1B\]\[4\]ldap\[1B\]\[C\]auth.langhua\[A3\]\[81\]\[CF\]0\[81\]\[CC\]\[A0\]\[3\]\[2\]\[1\]\[10\]\[A1\]\[3\]\[2\]\[1\]\[4\]\[A2\]\[81\]\[BF\]\[4\]\[81\]\[BC\].\[A3\],FO\[CC\]\[12\]P{r_l\[D5\]\[A1\]\[9F\]\[D9\]\[7F\]\[FF\]A2\[9C\]\[E1\]\[DB\]KZ%\[D9\]\[83\]\[AD\]\[C5\]j\[84\]\[87\]\[FD\]\[EB\]\[C9\]\]DGS\[8C\]%\[16\]\[7F\]&0\[BC\]r(\[BD\]\[11\]\[FF\]v\[EE\]V\[DD\]I\[EA\]E<\[B8\]\[B\]\[1D\]2\[D4\]>\[CB\]~1\[FB\]\[1\]fC\[1F\]5\[EA\]\[CD\]\[7\]\[E7\]\[DB\]\[B9\]\[B1\]\[14\]S\[95\]6?8Ea\[F5\]6\[8A\]\[BB\]\[8D\]V\[B9\]\[C1\]\[A5\]\[8\]\[C2\]LH,5\[1A\]\[BC\]"\[91\]v\[CC\]\[B2\]\[2\]QJd}\[97\]V\[A9\]g\[B5\]\[F6\]\[D0\]\[C4\]\[C9\],\!\[DF\]\[F8\]\[8E\]\[A3\]\[16\]\[7\]\[E5\])N\[E6\]\[11\] \[8\]+\[85\]\[FD\]\[1B\]\[11\]\[C3\]\[96\]\[98\]\[80\]}g<\[A3\]5\[1E\]\[BC\]si\[8A\]c9\[8A\]\[1A\]w\[13\]\[1E\]\[18\]\[87\](\[98\]\[E5\]\[E7\]\[89\]\[85\]W\[AC\]s\[A5\]v\[D6\]5v\[80\]\[A3\]\[FA\]\[A4\]\[81\]\[CA\]0\[81\]\[C7\]\[A0\]\[3\]\[2\]\[1\]\[10\]\[A2\]\[81\]\[BF\]\[4\]\[81\]\[BC\]\[15\]>\[D6\]\[CB\]h\[1B\]\[9\]Y\[AC\]\[C8\]hh\[F1\]_\[D4\]\[82\]GD\[FD\]4\[AA\]"$\[EC\]\[7F\]&\[B8\]\[F\]D\[7\]\[97\]\[82\]\[D\]\[A7\]\[D\]\[A2\]9\[8C\]\[88\]\[C0\]-\[DC\]\[E6\]\[A\]\[EB\]D6\[1F\]\[A4\]\[E2\]\[EE\]\[D1\]\[6\]x\[15\]\[D1\]\[EE\]4d\[86\]\[84\]\[99\]\[16\]\[AC\]\[F5\]C\[E8\]\[A9\]u#\[CE\]\[C5\]\[E1\]\[9B\]*\[E8\]\[B4\]\[93\]z\[E9\])\[15\]\[D\]L/E\[BD\]\[E6\]`\[1F\]_\[F2\]\[BC\]\[1A\]\[D7\]1\[BF\]\[C1\]\[2\]O\[8C\]\[1D\]\[A0\]\[C\]\[AB\]\[8B\]\[AB\]\[F5\]\[DB\]\[D4\]\[B1\]\[ED\]\[A\]\[AF\]\[9\]\[B\]s\[E9\]\[10\]\[FB\]u\[11\]\[E\]N\[1F\]*\[15\]\[AE\]h\[F5\]\[1C\]\[8E\]\[92\]\[AA\]6\|0\[F4\]\[FE\]\[CB\]\[9A\]\[9D\]c^o4\[CB\]\[8C\]\[B8\]\[99\]\[89\]\[A5\]\[18\]\[EA\]pE\[B1\]\[C7\]\[E8\]\[90\]\[82\]\[EE\]\[A6\](\[1A\]1Q\[D0\]\[81\]X\[C6\]q\[9B\]\[EA\]v\[C\]\[FA\]\[E9\]jd\[84\]\[BD\]\[CF\]\[90\]S\[8E\]P
recv: {153}
`\[81\]\[96\]\[6\]\[9\]*\[86\]H\[86\]\[F7\]\[12\]\[1\]\[2\]\[2\]\[2\]\[0\]o\[81\]\[86\]0\[81\]\[83\]\[A0\]\[3\]\[2\]\[1\]\[5\]\[A1\]\[3\]\[2\]\[1\]\[F\]\[A2\]w0u\[A0\]\[3\]\[2\]\[1\]\[10\]\[A2\]n\[4\]l\[5\],\[B7\]\[F6\]\[CD\]\[C\]\[BF\]\[1\]{*\[E0\]\[1F\]\[92\]\[FC\]\[10\]\[94\]U\[DF\]\[9E\]\[BA\]k_\[A4\]G&\[EC\]g:\[BA\]J\[C6\]\[C1\]sQ:'\[87\]/\[95\]\[C8\]W\[C5\]^47N\[9B\]im`\[BB\]\[B4\]\[C5\]\[EB\]\[BC\]w\[80\]\[A7\]\[1D\]Q\[89\]\[8B\]L\[8D\]N\[E7\]\[87\]\[C2\]\[EB\]\[D9\]k{j\[D\]\[AD\]\[A3\]w\[B1\]\[A2\]\[B3\]X\[FD\]"\[99\]LG\[88\]^\[DE\]\[CD\]\[ED\]\[AC\]\[F8\]\[10\](\[FA\]h\[2\]\[B7\]L\[E2\]K6\[2\]\[F5\]C\[91\]u
send: {0}

recv: {65}
`?\[6\]\[9\]*\[86\]H\[86\]\[F7\]\[12\]\[1\]\[2\]\[2\]\[2\]\[1\]\[4\]\[0\]\[FF\]\[FF\]\[FF\]\[FF\]\[91\]w\[FA\]J\[96\]\[9D\]4\[8F\]Is\[90\]\[89\]\[F\]\[B2\]\[BC\]X\[2\].\[C\];\[89\]\[9A\]\[3\]\[F9\]\[CF\]DU\[BA\]\[98\]x#\[CF\]\[FF\]G\[9E\]:\[1\]\[0\]\[0\]\[0\]\[4\]\[4\]\[4\]\[4\]
send: {73}
`G\[6\]\[9\]*\[86\]H\[86\]\[F7\]\[12\]\[1\]\[2\]\[2\]\[2\]\[1\]\[4\]\[0\]\[FF\]\[FF\]\[FF\]\[FF\]\[CB\]\[9F\]K\[D1\]\[81\]m\[E4\]\[A2\]\[A6\]\[E2\]\[C\]\[7F\]a\[8C\]\[1B\]\[A5\]\[CC\]m\[E6\]\[BB\]\[E4\]\[A4\]\[9F\]s\[B5\]\[F8\]\[1F\]\[D1\]\[3\]}\[95\]\[F1\]\[5\]\[C2\]s\[16\]\[1\]\[0\]\[0\]\[0\]test\[8\]\[8\]\[8\]\[8\]\[8\]\[8\]\[8\]\[8\]
successful authentication
closing connection

*GSSAPI is OK now.*&nbsp;

If the server and client can communicate but cannot authen successfully, perhaps it's caused by the driver of your ethernet card.

h1. Config OpenLDAP GSSAPI


h4. 1. ldapsearch \-Y GSSAPI \-b 'o=langhua,c=cn' '(ou=worldwide)'

SASL/GSSAPI authentication started
SASL username: test@AUTH.LANGHUA
SASL SSF: 56
SASL installing layers
\# extended LDIF
\#
\# LDAPv3
\# base <o=langhua,c=cn> with scope subtree
\# filter: (ou=worldwide)
\# requesting: ALL
\#

\# worldwide, langhua, cn
dn: ou=worldwide,o=langhua,c=cn
objectClass: organizationalUnit
objectClass: top
ou: worldwide

\# martin.peschke, worldwide, langhua, cn
dn: uid=martin.peschke,ou=worldwide,o=langhua,c=cn
uid: martin.peschke
ou: worldwide
objectClass: organizationalPerson
objectClass: uidObject
objectClass: person
objectClass: top
sn: Martin Peschke
cn: Martin Peschke

\# search result
search: 4
result: 0 Success

\# numResponses: 3
\# numEntries: 2

h4. 2. Edit /etc/slapd.conf
{code:title=/etc/slapd.conf|borderStyle=solid}
#
# See slapd.conf(5) for details on configuration options.
# This file should NOT be world readable.
#
include		/etc/openldap/schema/core.schema
include		/etc/openldap/schema/cosine.schema
include		/etc/openldap/schema/inetorgperson.schema
include		/etc/openldap/schema/nis.schema
include     /etc/openldap/schema/krb5-kdc.schema

# Allow LDAPv2 client connections.  This is NOT the default.
allow bind_v2

# Do not enable referrals until AFTER you have a working directory
# service AND an understanding of referrals.
#referral	ldap://root.openldap.org

pidfile		/var/run/openldap/slapd.pid
argsfile	/var/run/openldap/slapd.args

# Load dynamic backend modules:
# modulepath	/usr/lib/openldap
# moduleload	back_bdb.la
# moduleload	back_ldap.la
# moduleload	back_ldbm.la
# moduleload	back_passwd.la
# moduleload	back_shell.la

# The next three lines allow use of TLS for encrypting connections using a
# dummy test certificate which you can generate by changing to
# /etc/pki/tls/certs, running "make slapd.pem", and fixing permissions on
# slapd.pem so that the ldap user or group can read it.  Your client software
# may balk at self-signed certificates, however.
# TLSCACertificateFile /etc/pki/tls/certs/ca-bundle.crt
# TLSCertificateFile /etc/openldap/slapd.pem
# TLSCertificateKeyFile /etc/pki/tls/certs/slapd.pem
TLSCACertificateFile /etc/pki/demoCA/cacert.pem
TLSCertificateFile /etc/pki/demoCA/certs/ldap-cert.pem
TLSCertificateKeyFile /etc/pki/demoCA/certs/ldap-key.pem
# TLSVerifyClient demand

# Sample security restrictions
#	Require integrity protection (prevent hijacking)
#	Require 112-bit (3DES or better) encryption for updates
#	Require 63-bit encryption for simple bind
# security ssf=1 update_ssf=112 simple_bind=64

# disallow bind_simple

# Sample access control policy:
#	Root DSE: allow anyone to read it
#	Subschema (sub)entry DSE: allow anyone to read it
#	Other DSEs:
#		Allow self write access
#		Allow authenticated users read access
#		Allow anonymous users to authenticate
#	Directives needed to implement policy:
# access to dn.base="" by * read
# access to dn.base="cn=Subschema" by * read

#
# if no access controls are present, the default policy
# allows anyone and everyone to read anything but restricts
# updates to rootdn.  (e.g., "access to * by * read")
#
# rootdn can always read and write EVERYTHING!
# access to * by * read

#######################################################################
# ldbm and/or bdb database definitions
#######################################################################

database	bdb
suffix		"o=langhua,c=cn"
# rootdn		"uid=root,o=langhua,c=cn"
# Cleartext passwords, especially for the rootdn, should
# be avoided.  See slappasswd(8) and slapd.conf(5) for details.
# Use of strong authentication encouraged.
# rootpw		{SSHA}mpfjTVX6cJ+oMgoB1wIjJ8HTR/2kyBga

# The database directory MUST exist prior to running slapd AND 
# should only be accessible by the slapd and slap tools.
# Mode 700 recommended.
directory	/var/lib/ldap

# Indices to maintain for this database
index objectClass                       eq,pres
index ou,cn,mail,surname,givenname      eq,pres,sub
index uidNumber,gidNumber,loginShell    eq,pres
index uid,memberUid                     eq,pres,sub
index nisMapName,nisMapEntry            eq,pres,sub

# Replicas of this database
# replogfile /var/lib/ldap/openldap-master-replog
# replica host=ldap-1.example.com:389 starttls=critical
#     bindmethod=sasl saslmech=GSSAPI
#     authcId=host/ldap-master.example.com@EXAMPLE.COM


# authzTo: uid=[^,]*,o=langhua,c=cn

sasl-realm	AUTH.LANGHUA
sasl-host	auth.langhua

access to attrs=userPassword
        by self write
        by dn="uid=test,cn=auth.langhua,cn=gssapi,cn=auth" write
        by anonymous auth
        by * none

access to *
        by dn="uid=test,cn=auth.langhua,cn=gssapi,cn=auth" write
        by self write
        by * read
{code} 
\\