17 Eylül 2015 Perşembe

Socket Veri Yapıları

Giriş
Soket tiplerine göre API'de kullanılan veri yapıları değişkenlik gösteriyor.

Genel
sockaddr
Socket metodlarını çoklamamak için tüm struct'ların ortak atası gibi bir yapı düşünülmüş. Yapı şöyle tanımlı. sa_data'nın 14 bit olması tamamen tesadüf. Başka bir sayı da olabilirdi çünkü bir önemi yok.
struct sockaddr {
    sa_family_t sa_family;
    char        sa_data[14];
}
İşletim sistemi açısından önemli olan alan 2 byte uzunluğundaki sa_family alanı. sockaddr_in, sockaddr_in6 ve sockaddr_un veri yapılarının hepsinin ilk elemanı "family" yani soket çeşidini gösteren alan ile başlar.

Bu yapı ile sendto, bind vs. gibi metodların hepsinde paramtre olarak geçiliyor. Örneğin bind metodunun imzası şöyle.
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

IPV4
sockaddr_in
Bu yapı IPv4 ile kullanılan en temel yapı. İçi şöyle
struct sockaddr_in {
    short            sin_family;   // e.g. AF_INET, AF_INET6
    unsigned short   sin_port;     // e.g. htons(3490)
    struct in_addr   sin_addr;     // see struct in_addr, below
    char             sin_zero[8];  // zero this if you want to
}; 
Linux'ta şöyle tanımlı. Yukarıdaki yapı ile aynı kapıya çıkıyor.
struct sockaddr_in {
    sa_family_t    sin_family; /* address family: AF_INET */
    in_port_t      sin_port;   /* port in network byte order */
    struct in_addr sin_addr;   /* internet address */
};

/* Internet address. */
struct in_addr {
    uint32_t       s_addr;     /* address in network byte order */
};

Windows dünyasında bu yapı büyük harflerler yazılmış. Yani SOCKADDR_IN şeklinde.

sockaddr_in bind(), connect() ,sento() metodlarına parametere olarak geçilir.
accept(), recvfrom(), getsockname(), getpeername() metodları ise sockaddr_in parametresini doldurarak döndürürler.

Bu yapı şöyle doldurulur. Beni en gıcık eden şey sin_addr.s_addr alanını bir türlü hatırlayamamam.

struct sockaddr_in clientService;
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr("10.0.0.1");                            
clientService.sin_port = htons(80); 
in_addr
Bu veri yapısı IPv4 adresini binary olarak saklamaya yarar

IPV6
sockaddr_in6
Bu yapı IPv6 ile kullanılan en temel yapı. İçi şöyle
struct sockaddr_in6 {
    u_int16_t       sin6_family;   // address family, AF_INET6
    u_int16_t       sin6_port;     // port number, Network Byte Order
    u_int32_t       sin6_flowinfo; // IPv6 flow information
    struct in6_addr sin6_addr;     // IPv6 address
    u_int32_t       sin6_scope_id; // Scope ID
};

struct in6_addr {
    unsigned char   s6_addr[16];   // IPv6 address
};

Ethernet
sockaddr_ll
Bu veri yapısı Linux'ta ethernet seviyesinde veri göndermek için kullanılır.

Unix
sockaddr_un
Yapı şöyle
struct sockaddr_un {
    sa_family_t sun_family;               /* AF_UNIX */
    char        sun_path[108];            /* pathname */
};





9 Eylül 2015 Çarşamba

WSDL Anatomisi

Giriş
WSDL dosyasını gözle okumak biraz zor. SoapUI gibi bir program ile görsel olarak bakmak daha kolay.

wsdl dosyasının anatomisi hakkında aldığım notlar aşağıda.wsdl dosyasının parçalarını gösteren bir şekil burada

Mantıksal Bölümler
wsdl dosyası mantıksal olarak şöyle bölümleniyor.

Message Definition Bölümü - Interface metodların girdi, çıktı parametrelerinin tanımları
Şeklen şöyledir
<wsdl:message name="IHealthCheckService_GetDiskCFreeMb_InputMessage">
  <wsdl:part name="parameters" element="tns:GetDiskCFreeMb"/>
</wsdl:message>
Interface Definition Bölümü
Şeklen şöyledir.
<wsdl:portType name="IHealthCheckService">
  <wsdl:operation name="GetDiskCFreeMb">
    <wsdl:input message="tns:GetDiskCFreeMb_InputMessage" wsam:Action=""/>
    <wsdl:output message="tns:OutputMessage" wsam:Action=""/>
  </wsdl:operation>
</wsdl:portType>
Binding Bölümü
Şeklen şöyledir
<wsdl:binding name="" type="">
  <soap:binding transport=""/>
    <wsdl:operation name="">
      <soap:operation style="document" soapAction=""/>
        <wsdl:input>
          <soap:body use="literal"/>
        </wsdl:input>
        <wsdl:output>
          <soap:body use="literal"/>
        </wsdl:output>
        </wsdl:operation>
</wsdl:binding>
Service Bölümü - Interface Implementation
Şeklen şöyledir
<wsdl:service name="">
  <wsdl:port name="" binding="">
    <soap:address location=""/>
  </wsdl:port>
</wsdl:service>
Interface Definition Detayları

Operation Etiketi
Örnek
<operation name="convertLead">
    <documentation>convert a set of leads</documentation>
    <input  message="tns:convertLeadRequest"/>
    <output message="tns:convertLeadResponse"/>
    <fault  message="tns:UnexpectedErrorFault" name="UnexpectedErrorFault"/>
</operation>
input girdi output ise çıktı parametereleri belirtir. Parametreler message etiketi içinde tanımlıdır.

Message Etiketi
Örnek
<message name="convertLeadRequest">
    <part element="tns:convertLead" name="parameters"/>
</message>
<message name="convertLeadResponse">
    <part element="tns:convertLeadResponse" name="parameters"/>
</message>
Element Etiketi
Örnek
<element name="convertLead">
 <complexType>
  <sequence>
   <element name="leadConverts" type="tns:LeadConvert" 
            minOccurs="0" maxOccurs="unbounded"/>
  </sequence>
 </complexType>
</element>

Interface Implementation Detayları

Service Etiketi
<service>...</service> etiketi ile verilen servisin nasıl bir port'a hizmet edeceği tanımlı. Port'u Java olarak düşünürsek arayüz (interface) tanımı, binding'i ise gerçekleştiren sınıf olarak hayal edebiliriz.

Binding Etiketi
<binding>...</binding> etiketi ile verilen servisin hangi protokolü kullanacağı ve metodları olacağı tanımlı.

Burada style="document" yazan kısma dikkat etmek lazım. Üretilen WSDL Document/Literal Bare veya Document/Literal Wrapped formatında olabilecek şeklinde ayarlanabiliyor. Hiç bir şey belirtilmezse Document/Literal Wrapped formatı kullanılıyor.

Document/Literal Wrapped ile SOAP mesajında çağırılmak istenen metodun ismi ve parametreleri de belirtilmiş oluyor.   JAX-WS ile açık bir şekilde tanımlamak istenirse aşağıdaki gibi tanımlamak lazım.

8 Eylül 2015 Salı

sudo komutu

Giriş
sudo ile ilgili notlarım aşağıda.

sudo verilen komutu root olarak çalıştırır
Örneğin
sudo cp /etc/foo.txt ~/foo.txt
komutu çalıştırılınca yeni oluşturulan foo.txt dosyasının sahibi root olur.

sudo sadece kendisinden sonra gelen komutu çalıştırır
Şöyle bir şey yazarsak
sudo some-command && some-other-command
Sadece ilk komut root olarak çalışır. && işaretinden sonra gelen komut normal kullanıcı olarak çalışır.

-i seçeneği
interaktif bir kabuk açmamız sağlar. Kabuğun promt'u # olaral değişir.

-u seçeneği
-u seçeneği başka bir kullanıcı olarak çalıştırma imkanı tanır. Örnekte whoami başka bir kullanıcı olarak çalıştırılınca sonucun farklı olduğu görülebilir.
$ whoami
admin
$ sudo -S -u otheruser whoami
otheruser
sudo komutu root şifresini bilmeyi gerektirmez
sudo komutu kullanıcının kendi şifresini girmesini bekler. Böylece kullanıcıyı doğrular. Tabiki kullanıcının sudo grubuna dahil olması gerekir. Hangi gruba dahil olduğumuz görmek için groups komutu çalıştırılabililir.
> groups
> adm cdrom sudo dip plugdev lpadmin sambashare

sudoers dosyası
/etc/sudoers dosyası şuna benzer. visudo komutu ile /etc/sudoers dosyası düzenlenebilir.

Satır Formatı
Dosya içindeki kullanıcı ve grup satırları şuna benzer ve 4 alandan oluşur.
superadm  ALL=(ALL)   ALL
1 alan : Kullanıcı adı veya grup adını belirtir. Grup adları % işareti ile başlar.
2 alan : sudo'nun yetkili olduğu makine isimlerini belirtir. Genellikle ALL ile localhost kastedilir.
3 alan (...) şeklinde yazılır. İlk alanda belirtilen grubun -u seçeneği ile hangi grubu taklit edebileceğini belirtir. ALL ile sınırlama konulmaz. Eğer boş bırakılırsa root olabileceği belirtilir.
4 alan : sudo olarak çalıştırılabilecek komutlar listelenir. ALL ise tüm komutlar için sudo yapılabilir.

kullanıcı ve gruplar
Ubuntu kurulumunda sudo ve admin grupları ve root kullanıcısı kendiliğinden her türlü yetkiye sahip olarak geliyor.  Hiç dokunulmamış bir sudoers dosyası şuna benzer.
# User privilege specification
root    ALL=(ALL:ALL) ALL

# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL

# Allow members of group sudo to execute any command
%sudo   ALL=(ALL:ALL) ALL
kullanıcıyı sudo grubuna eklemek
Yeni bir kullanıcı sudo yapabilsin istiyorsak onu sudo grubuna şöyle ekleriz.
sudo adduser bob sudo
şifre
sudo şifre sormasın istersek son satırı şöyle yaparız.
%sudo   ALL=(ALL:ALL) NOPASSWD: ALL
sudo komutu için path
sudo komutu sistem path'ine bakmaz. $PATH değişkenini düzenlesek bile yeni dizini görmez. sudoers dosyasındaki şu satırı düzenlemek gerekir.
Defaults        secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:$
grup ve komut kısıtı eklemek
Bir kişiye belli bir komutu root olarak çalıştırma hakkı vermek için şöyle yaparız
bob ALL=(root) NOPASSWD: /path/to/command/you/trust
Eğer bir kişiye specialuser grubuna ait olarak belli bir komutu çalıştırma hakkı vermek için şöyle yaparız
bob ALL=(specialuser) NOPASSWD: /path/to/command/you/trust
Sadece belli dosya kısıtı ekleme
Eğer bir gruba veya kullanıcıya belli komutlar için hak tanımak istersek şöyle yaparız.
username   ALL = (named) /usr/sbin/named
Kullanıcı komutu şöyle çalıştırır
sudo -u named /usr/sbin/named
Örnekte sudoedit komutunu sadece belli dosyalar üzerinde çalıştırma yetkisi veriliyor.
user ALL=(ALL) sudoedit /etc/httpd/conf/httpd.conf /etc/httpd/conf.d/*.conf
timestamp
sudo şifresinin belli bir süre hatırlanmasını istiyorsak bu alanı kullanırız.
Defaults        timestamp_timeout=300









Self signed certificate

Neden Root CA Üretiriz
Local Certificate Authority yazısına taşıdım.

Sertifika Uyarısı
Bazen site adı ile sertifikası uyuşmaz. O zaman tarayıcı uyarı verir. Aşağıda bir örnek var.
Güvenlik Sertifikası
Site adı sertifika üzerindeki adla uyuşmuyor.
Düzenlenen kişi


Genel ad:
  *.tai.com.tr

Organizasyon:
TUSAS TURK HAVACILIK VE UZAY SANAYI A.S.

Kurumsal birim:
BILISIM DESTEK MUDURLUGU

Düzenleyen

Genel ad:
TÜRKTRUST Elektronik Sunucu Sertifikası Hizmetleri

Organizasyon:
TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş.(c) Kasım 2005

Kurumsal Birim:

Geçerlilik:
Düzenleme tarihi:
31 01 2011

Sona erme tarihi:
30 01 2014


Java İle İlgili Notlarım

Java keystore dosyası içinde iki çeşit girdi var. İlki trustedCertEntry diğeri ise keyEntry.

trustedCertEntry
SSL ile el sıkışma esnasında sertifikayı yayınlayan CA'nın istemci (client) tarafından biliniyor olması gerekir. CA sertifikasının içinde CA otoritesinin public anahtarı bulunmaktadır.

CA Listeleme
Normalde JVM ile çok kullanılan CA'lar tanımlı olarak geliyorlar. Tanımlı CA'lar şöyle listelenebilir.
keytool -list -keystore cacerts >> /opt/app/temp/<filename_here>
CA Tanımlama
Ancak bazı CA'lar tanımlı olmayabilirler. Eğer sistemde tanımlı bulunmayan CA'nın sertifikasını girmek istiyorsak aşağıdaki komutu kullanıyoruz.

keytool -import -v -trustcacerts -alias myServer -file caCert.cer -keystore $JAVA_HOME/jre/lib/security/cacerts


Bu komutta trustcacerts parametresi ile CA sertifikasını aldığımızı belirtiyoruz. caCert.cer ise CA'nın sertifikası.

Dikkat edilmesi gereken nokta  benim sistemimde cacerts dosyası bulunduğu için bu komutu kullandım.
Aslında CA sertifikası sistemden aşağıdaki yerlerden birinde bulunabilir ve kullanılan komutta keystore'un nerede olduğu değişebilir.

  • If the system property "javax.net.ssl.trustStore" is defined, the TrustManager tries to find the default trustStore file by using the filename specified by that system property.
  • If the "javax.net.ssl.trustStore" system property was not specified, and if the file "<java-home>/lib/security/jssecacerts" exists, that file is used.
  • If the file "<java-home>/lib/security/cacerts" exists, that file is used.


keyEntry
keyEntry public/private anahtarları içerir.

keytool - genkey komutu ile üretiliyor. Oracle dokümanında örnekler var. Üretilen sertifika için kullanılacak algoritmayı seçebiliyoruz. Örneğin RSA'yı seçmek için aşağıdaki komut kullanılabilir.

keytool -genkey -alias tomcat -keyalg RSA

Eğer keystore ile sertifikayı almak istemiyorsaj JVM'e çalışma parametresi olarak verebiliriz. Örnek,
java -Djavax.net.ssl.trustStore=c:\jdk160_29\.mykeystore

Certificate Request Nedir
Önce kendi private ve public anahtalarımızı oluşturuyoruz. Sonra public anahtarımızı ve bilgilerimizi bir CA'ya gönderiyoruz. CA da kendi private anahtarı ile bizim public anahtarımızı şifreleyip bize geri gönderiyor. Böylece bizi tanımlayan bir kimlik oluşuyor.
 
Intermediate CA (Certificate Authority) 'dan Satın Aldığımız Sertifikamızı Kurmak

Bir Intermediate CA'dan satın aldığımız sertifika aynı zamanda Primary Sertifika olarak ta adlandırılıyor. Bizi tanımlayan kimlik anlamına geliyor. İçinde bizim public key'imiz var diye anlıyorum.

Java ile bu işi yaparken aşağıdaki komutu kullanıyoruz. Aşağıdaki örneği buradan aldım.
İşlem bittikten sonra certfile.cer dosyasınıa artık ihtiyacımız kalmıyor ve silinebilir.
------------------------------------------
Bir başka örnekte ise Tomcat'e kurma komutu verilmiş.


keytool -import -trustcacerts -alias tomcat -file PrimaryCertFileName.crt -keystore keystore.key 

İşlemi yaparken keystore.key dosyasına erişim için şifre istenecek. Bu keystore dosyasını oluştururken kullandığımı şifreyi kullanmamız lazım.

Web Servis İle Bir Başka Kurumun Servisine Erişim İçin Sertifika Kurmak
Buradaki örnekte de görüldüğü gibi yukarıdaki işlemler ile aynı komut çalıştırılıyor.

keytool -import -trustcacerts -keystore $JAVA_HOME/lib/security/cacerts -file /Users/..../Sertifika/ptt.pem



SSL
SSL ile tek yönlü veya iki yönlü kimlik doğrulama mümkün. Nasıl çalıştığını gösteren bulabildiğim en güzel şekilleri buradan aldım ve aşağıya ekledim.

Tek yönlü doğrulama

Çift yönlü doğrulama


4 Eylül 2015 Cuma

Programlama Dillerinde Access Modifier Kullanımı

Giriş
Access Modifier'ın Türkçesi Erişim Belirleyici. Ama ben İngilizcesini kullanmayı daha uygun buldum.

C++
Sınıf seviyesinde access modifier
C++'ta Javadaki gibi class'ları gizlemek için access modifier yok. Burada classları gizlemek için bazı çözümler verilmiş.

1. İlk çözüm sınıfı bir başka sınıf içinde gizlemek.
Ben bu kullanım şeklini header dosyası halen görülebildiği için sevmiyorum. Örnek
class outer{
private: 
    class inner{
    private:
        int something;
    public:
        void print(){
            std::cout<< "i am inner"<<std::endl;
        }   
    };
public:
    inner returnInner(){
        inner i;
        return i;
    }  
};
Bu kullanım şeklinde aslında sınıf tam anlamıyla gizlenmiyor. (2) ve (3) ile işaretli satırlar halen derleniyor.
int main(){
    outer o;
    //outer::inner i = o.returnInner(); (1)
    //auto i = o.returnInner();         (2)
    //i.print();                  
    o.returnInner().print();          //(3)
    return 0;
}
C++11 ile nested sınıf dıştaki sınıfın private alanlarına da erişebiliyor.
A nested class is a member and as such has the same access rights as any other member.
a.) Arayüz ile kullanılması
Bir başka örnek'te tcp_stream nested olmasına rağmen belli bir arayüz gibi kullanılıyor.
class stream {
    virtual void write(const std::string text) = 0;
};

class channel {
public:
    virtual stream* get_stream() = 0;

    // Other methods...
};

class tcp_channel : public channel {
public:
    virtual stream* get_stream() {
        return new tcp_stream(this);
    }

private:
    class tcp_stream : public stream { /* implementation */ };
};
b) Kalıtım recursive olması
Bu kullanım şekli daha da tuhaf
class protocol {
public:
    virtual void create_connection() = 0;

    class tcp : public protocol { /* implementation */ };
    class shared_memory : public protocol { /* implementation */ };
    class named_pipes: public protocol { /* implementation */ };
};

auto media = protocol::tcp();
2. Header dosyasına yazmama çözümü
Diğeri ise gizlenmek istenen sınıfı header dosyası değil cpp dosyasına yazmak. Önce sadece Worker sınıfı .h dosyasında tanımlanıyor.
class Worker{
    //some class definition
};
Daha sonra Hidden sınıfı cpp dosyasında tanımlanıyor.
#include "worker.h"
class Hidden{
    //some class definition
};
//implementation of Worker class which uses Hidden class
Eğer  worker.h include edilse bile Hidden sınıfına erişilemez!
//if you only include the header, the class Hidden does not exist
#include "worker.h"
Bu kullanım şeklinin dezavantajı ise Hidden isimli ikinci bir sınıf daha yaratamamız. Her ne kadar dışarıdan erişim olmasa bile özellikle birim testlerde yaparken ikinci bir Hidden sınıfı yaratmak gerekiyor ancak yapamıyoruz.

Java
Metod ve Member Variable seviyesinde access modifier
Java'nın şöyle
            | Class | Package | Subclass | World
————————————+———————+—————————+——————————+———————
public      |  y    |    y    |    y     |   y
————————————+———————+—————————+——————————+———————
protected   |  y    |    y    |    y     |   n
————————————+———————+—————————+——————————+———————
no modifier |  y    |    y    |    n     |   n
————————————+———————+—————————+——————————+———————
private     |  y    |    n    |    n     |   n

y: accessible
n: not accessible



Friendly
Friendly package default anlamına gelir. Package default yerine bazen package private ta kullanılır. Sadece paket içinden erişim anlamına gelir.

Protected
Protected olan alana, sınıf'tan kalıtanlar (farklı paket içinde olsa bile) ve aynı paket içinde olan sınıflar (kalıtım ilişkisi olmasa bile) erişebilirler.

Interface
Interface içindeki metodlar yazılmasa bile public kabul edilir. Örnekte f metodu public'tir.
public interface MyInterface {
  void f();
}

Sınıf seviyesinde access modifier

package-private
Sınıfın başına hiç bir access modifier yazılmazsa package-private kabul edilir. Sınıf sadece içinde bulunduğu paket tarafından erişilebilir.  Örnek'te  animals paketini import eden kişi Platypus sınıfına erişemeyeceği gösteriliyor.
package animals;

public class Animal { ... };

public class Giraffe extends Animal {
    void Run() { ... }
    public void Jump() { ... }
}

class Platypus extends Animal { ... }

C#
Sınıf metodlarının default access modifier seviyesi private'tır. Yani dışarıdan erişilemezler.
Sınıfların default access modifier seviyesi internal'dır. Yani sadece kendi assembly'sinden erişilebilir.

Internal
Şöyle tanımlanıyor.

The internal keyword is an access modifier for types and type members. Internal types or members are accessible only within files in the same assembly, as in this example

Internal bir field örneği
public class MyClass 
{
    // Only accessible within the same assembly
    internal static int x = 0;
}